@c8y/style 1023.30.0 → 1023.42.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.
Files changed (265) hide show
  1. package/branding-login.less +1 -1
  2. package/helper-scripts/README-variable-imports.md +155 -0
  3. package/helper-scripts/README.md +104 -0
  4. package/helper-scripts/convert-scss-to-less.sh +512 -0
  5. package/helper-scripts/convert-stroke-icons-to-less.js +115 -0
  6. package/helper-scripts/remove-redundant-variable-imports.sh +80 -0
  7. package/helper-scripts/scss-to-less-skip +20 -0
  8. package/{sync-scss-to-less.sh → helper-scripts/sync-scss-to-less.sh} +2 -2
  9. package/helper-scripts/test-compile.sh +71 -0
  10. package/img/pie-chart-widget-pr.png +0 -0
  11. package/markdown-files/MANUAL-SYNC-FILES.md +56 -0
  12. package/package.json +2 -2
  13. package/styles/_login-app.less +34 -0
  14. package/styles/_login-app.scss +2 -2
  15. package/styles/_mixins.less +47 -0
  16. package/styles/_utilities.less +21 -0
  17. package/styles/_utilities.scss +1 -0
  18. package/styles/animations/_animate.less +18 -13
  19. package/styles/animations/_component-animations.less +18 -16
  20. package/styles/animations/_realtime-animation-list.less +11 -1
  21. package/styles/animations/_spinner-snake.less +17 -2
  22. package/styles/animations/_spinner.less +24 -6
  23. package/styles/base/_normalize.less +14 -0
  24. package/styles/base/_print.less +25 -12
  25. package/styles/base/_scaffolding.less +24 -28
  26. package/styles/base/_type.less +41 -19
  27. package/styles/components/_markdown-content.less +4 -1
  28. package/styles/components/_smartrules.less +14 -8
  29. package/styles/components/_smartrules.scss +6 -2
  30. package/styles/components/application-and-system/_c8y-cookie-banner.less +36 -0
  31. package/styles/components/{specialized → application-and-system}/_c8y-login.less +20 -6
  32. package/styles/components/data-display-and-visualization/_boxed-label.less +45 -0
  33. package/styles/components/data-display-and-visualization/_boxed-label.scss +46 -0
  34. package/styles/components/{specialized → data-display-and-visualization}/_c8y-data-explorer.less +37 -23
  35. package/styles/components/{specialized → data-display-and-visualization}/_c8y-datapoint-pill.less +29 -13
  36. package/styles/components/{specialized → data-display-and-visualization}/_c8y-pulse.less +33 -6
  37. package/styles/components/data-display-and-visualization/_range-display.less +25 -16
  38. package/styles/components/{specialized → data-display-and-visualization}/_smart-list-icon-label.less +19 -5
  39. package/styles/components/{specialized → data-display-and-visualization}/_status.less +16 -2
  40. package/styles/components/{specialized → data-display-and-visualization}/_statusContainer.less +16 -2
  41. package/styles/components/data-display-and-visualization/_timelines-chart.less +2 -0
  42. package/styles/components/data-display-and-visualization/lists/_c8y-data-point-list.less +10 -0
  43. package/styles/components/data-display-and-visualization/lists/_c8y-empty-state.less +26 -12
  44. package/styles/components/data-display-and-visualization/lists/_c8y-list-group.less +83 -43
  45. package/styles/components/data-display-and-visualization/lists/_cards-layout.less +38 -16
  46. package/styles/components/data-display-and-visualization/lists/_list-group.less +46 -28
  47. package/styles/components/data-display-and-visualization/lists/_smart-rules-template-list.less +12 -1
  48. package/styles/components/data-display-and-visualization/lists/{timeline-list.less → _timeline-list.less} +46 -24
  49. package/styles/components/data-display-and-visualization/tables/_data-grid.less +45 -25
  50. package/styles/components/data-display-and-visualization/tables/_resizable-grid.less +18 -5
  51. package/styles/components/data-display-and-visualization/tables/_tables.less +25 -9
  52. package/styles/components/data-input/_c8y-ai-chat.less +1 -0
  53. package/styles/components/{specialized → data-input}/_c8y-countdown-interval.less +15 -13
  54. package/styles/components/{specialized → data-input}/_c8y-range.less +22 -6
  55. package/styles/components/{specialized → data-input}/_dtm-icon-selector.less +17 -2
  56. package/styles/components/{specialized → data-input}/_dtm-icon-selector.scss +1 -2
  57. package/styles/components/{specialized → data-input}/_measurements-time-control.less +34 -6
  58. package/styles/components/{specialized → data-input}/_measurements-time-control.scss +14 -2
  59. package/styles/components/{specialized → data-input}/_search-header.less +22 -6
  60. package/styles/components/data-input/_static-assets-file-picker.less +22 -0
  61. package/styles/components/data-input/assets/_asset-property-list.less +38 -23
  62. package/styles/components/data-input/assets/_asset-table.less +21 -3
  63. package/styles/components/data-input/assets/_c8y-asset-notes.less +13 -1
  64. package/styles/components/data-input/assets/_c8y-asset-selector-miller.less +27 -8
  65. package/styles/components/data-input/assets/_c8y-asset-selector.less +32 -15
  66. package/styles/components/data-input/assets/_c8y-child-assets-selector.less +90 -9
  67. package/styles/components/{specialized → forms}/_c8y-schema-form.less +44 -17
  68. package/styles/components/{specialized → forms}/_c8y-schema-form.scss +15 -3
  69. package/styles/components/{specialized → navigation-and-layout}/_c8y-role-card.less +21 -5
  70. package/styles/components/{specialized → navigation-and-layout}/_c8y-scrollbar.less +24 -7
  71. package/styles/components/{specialized → navigation-and-layout}/_c8y-smart-rest-tab.less +21 -6
  72. package/styles/components/{specialized → navigation-and-layout}/_c8y-stepper.less +15 -1
  73. package/styles/components/{specialized → navigation-and-layout}/_c8y-user-roles.less +45 -28
  74. package/styles/components/{specialized → navigation-and-layout}/_device-software-tab.less +14 -0
  75. package/styles/components/navigation-and-layout/action-bars/_app-switcher.less +27 -5
  76. package/styles/components/navigation-and-layout/action-bars/_c8y-action-bar.less +49 -21
  77. package/styles/components/navigation-and-layout/cards/_card-dashboard.less +25 -4
  78. package/styles/components/navigation-and-layout/cards/_card-flip.less +41 -14
  79. package/styles/components/navigation-and-layout/cards/_card-grid.less +20 -4
  80. package/styles/components/navigation-and-layout/cards/_card.less +90 -75
  81. package/styles/components/navigation-and-layout/cards/_panels.less +38 -20
  82. package/styles/components/navigation-and-layout/navigation/_breadcrumbs.less +21 -39
  83. package/styles/components/navigation-and-layout/navigation/_c8y-nav-stacked.less +26 -14
  84. package/styles/components/navigation-and-layout/navigation/_main-header.less +41 -13
  85. package/styles/components/navigation-and-layout/navigation/_main-header.scss +1 -1
  86. package/styles/components/navigation-and-layout/navigation/_navbar.less +22 -25
  87. package/styles/components/navigation-and-layout/navigation/_navbar.scss +7 -7
  88. package/styles/components/navigation-and-layout/navigation/_navigator.less +71 -69
  89. package/styles/components/navigation-and-layout/navigation/_navs.less +13 -0
  90. package/styles/components/navigation-and-layout/navigation/_pagination.less +24 -5
  91. package/styles/components/navigation-and-layout/navigation/{steps-navbar.less → _steps-navbar.less} +7 -6
  92. package/styles/components/navigation-and-layout/navigation/_tabs.less +18 -14
  93. package/styles/components/navigation-and-layout/navigation/_tabs.scss +2 -2
  94. package/styles/components/{specialized → status-feedback-and-notifications}/_c8y-message-banner.less +14 -0
  95. package/styles/components/{specialized → status-feedback-and-notifications}/_code.less +18 -2
  96. package/styles/core/buttons/_button-groups.less +29 -79
  97. package/styles/core/buttons/_buttons.less +229 -198
  98. package/styles/core/buttons/_buttons.scss +6 -10
  99. package/styles/core/feedback/_alerts.less +52 -41
  100. package/styles/core/feedback/_badges.less +29 -17
  101. package/styles/core/feedback/_close.less +24 -7
  102. package/styles/core/feedback/_labels.less +21 -8
  103. package/styles/core/feedback/_progress-bars.less +24 -7
  104. package/styles/core/feedback/_tag.less +23 -6
  105. package/styles/core/feedback/_tooltip.less +44 -20
  106. package/styles/core/forms/_c8y-switch.less +39 -19
  107. package/styles/core/forms/_c8y-switch.scss +37 -29
  108. package/styles/core/forms/_file-picker.less +79 -61
  109. package/styles/core/forms/_forms.less +130 -133
  110. package/styles/core/forms/_input-groups.less +110 -59
  111. package/styles/core/forms/_input-groups.scss +21 -3
  112. package/styles/core/overlays/_c8y-dashboard-modal.less +25 -29
  113. package/styles/core/overlays/_c8y-wizard.less +38 -15
  114. package/styles/core/overlays/_dropdowns.less +86 -63
  115. package/styles/core/overlays/_modals.less +58 -40
  116. package/styles/core/overlays/_popovers.less +25 -9
  117. package/styles/dashboard/_availability-pie.less +3 -0
  118. package/styles/dashboard/_c8y-dashboard-style.less +61 -34
  119. package/styles/dashboard/_c8y-gauges.less +20 -4
  120. package/styles/dashboard/_dashboard-widgets.less +17 -4
  121. package/styles/dashboard/_info-gauge.less +20 -5
  122. package/styles/dashboard/_quick-links-widget.less +13 -3
  123. package/styles/{welcome-widget.less → dashboard/_welcome-widget.less} +21 -4
  124. package/styles/dashboard/{welcome.less → _welcome.less} +54 -45
  125. package/styles/icons/_c8y-glyphs.less +12 -1
  126. package/styles/icons/_c8y-glyphs.scss +2 -1
  127. package/styles/icons/_c8y-icons.less +214 -199
  128. package/styles/icons/_dlt-c8y-icons-stroke.less +7238 -1834
  129. package/styles/icons/_dlt-c8y-icons.less +14 -0
  130. package/styles/icons/_marker-icons.less +10 -0
  131. package/styles/index.less +160 -134
  132. package/styles/index.scss +53 -29
  133. package/styles/layout/_bottom-drawer.less +21 -7
  134. package/styles/layout/_c8y-help-drawer.less +30 -9
  135. package/styles/layout/_c8y-right-drawer.less +34 -19
  136. package/styles/layout/_c8y-top-drawer.less +43 -28
  137. package/styles/layout/_grid.less +18 -4
  138. package/styles/layout/_group-info.less +14 -2
  139. package/styles/layout/_layouts.less +48 -30
  140. package/styles/layout/_mcontainer.less +26 -12
  141. package/styles/layout/_page-tabs.less +115 -23
  142. package/styles/layout/_split-scroll.less +16 -4
  143. package/styles/layout/_split-view.less +19 -5
  144. package/styles/login-app-use.scss +2 -2
  145. package/styles/login-app.less +4 -4
  146. package/styles/mixins/_buttons.scss +1 -0
  147. package/styles/mixins/{color-mixins.less → _color-mixins.less} +2 -2
  148. package/styles/mixins/{element-queries.less → _element-queries.less} +2 -2
  149. package/styles/mixins/{forms.less → _forms.less} +1 -1
  150. package/styles/mixins/_gradients.less +117 -0
  151. package/styles/mixins/{grid-framework.less → _grid-framework.less} +21 -21
  152. package/styles/mixins/_icon-base.less +29 -0
  153. package/styles/mixins/{nav-vertical-align.less → _nav-vertical-align.less} +6 -2
  154. package/styles/mixins/_nav-vertical-align.scss +5 -2
  155. package/styles/mixins/{progress-bar.less → _progress-bar.less} +1 -1
  156. package/styles/mixins/{shadows-helper.less → _shadows-helper.less} +3 -5
  157. package/styles/mixins/_shadows-helper.scss +1 -4
  158. package/styles/mixins/{vendor-prefixes.less → _vendor-prefixes.less} +7 -22
  159. package/styles/mixins/_vendor-prefixes.scss +1 -17
  160. package/styles/utilities/_borders.less +21 -11
  161. package/styles/{components/specialized → utilities}/_c8y-utils.less +14 -0
  162. package/styles/{components/specialized → utilities}/_c8y-utils.scss +1 -1
  163. package/styles/utilities/_caret.less +18 -4
  164. package/styles/utilities/_container-queries.less +11 -3
  165. package/styles/utilities/_contextual-colors.less +48 -119
  166. package/styles/utilities/_display.less +26 -41
  167. package/styles/utilities/_elevation.less +17 -7
  168. package/styles/utilities/_flex-containers.less +10 -0
  169. package/styles/utilities/_flex-items.less +11 -0
  170. package/styles/utilities/_icon-utils.less +15 -3
  171. package/styles/utilities/_margins-paddings.less +23 -4
  172. package/styles/utilities/_overflows.less +10 -0
  173. package/styles/utilities/_position.less +11 -0
  174. package/styles/utilities/_quickfloats.less +20 -1
  175. package/styles/utilities/_separators.less +11 -0
  176. package/styles/utilities/_shadows.less +5 -49
  177. package/styles/{utilities.less → utilities/_sizing.less} +13 -21
  178. package/styles/utilities/_text-utils.less +35 -24
  179. package/styles/vendor/ace-editor/_ace-editor.less +1 -0
  180. package/styles/vendor/angular/_loading-bar.less +1 -0
  181. package/styles/vendor/angular/_ui-sortable.less +2 -1
  182. package/styles/vendor/angular/_uib-accordion.less +1 -0
  183. package/styles/{angular-ui-select/select.less → vendor/angular/angular-ui-select/_select.less} +2 -10
  184. package/styles/vendor/cdk/_cdk-drag.less +3 -0
  185. package/styles/vendor/cdk/_cdk-tree.less +6 -3
  186. package/styles/vendor/cdk/_cdk-virtual-scroll-window.less +1 -0
  187. package/styles/vendor/datepicker/_bs-datepicker.less +26 -6
  188. package/styles/vendor/datepicker/_uib-datepicker.less +37 -4
  189. package/styles/vendor/leaflet/_c8y-map-internal.less +44 -54
  190. package/styles/vendor/leaflet/_leaflet.less +4 -1
  191. package/styles/vendor/other/_colorpicker.less +3 -2
  192. package/styles/vendor/selectize/_c8y-selectize.less +33 -10
  193. package/variables/_color-defaults.less +29 -10
  194. package/variables/_color-defaults.scss +29 -10
  195. package/variables/_color-vars.less +37 -89
  196. package/variables/_color-vars.scss +19 -77
  197. package/variables/{login-vars.less → _login-vars.less} +3 -5
  198. package/variables/index.less +3 -3
  199. package/variables/tokens/{c8y-design-tokens-dark.less → _c8y-design-tokens-dark.less} +5 -1
  200. package/variables/tokens/{c8y-design-tokens.less → _c8y-design-tokens.less} +5 -1
  201. package/styles/components/specialized/_boxed-label.less +0 -21
  202. package/styles/components/specialized/_boxed-label.scss +0 -36
  203. package/styles/components/specialized/_c8y-cookie-banner.less +0 -22
  204. package/styles/components/specialized/_static-assets-file-picker.less +0 -8
  205. package/styles/dashboard/welcome-widget.less +0 -50
  206. package/styles/mixins/gradients.less +0 -142
  207. package/styles/mixins.less +0 -45
  208. package/styles/steps-navbar.less +0 -97
  209. package/styles/timeline-list.less +0 -210
  210. package/styles/vendor/angular/angular-ui-select/select.less +0 -161
  211. package/styles/welcome.less +0 -128
  212. /package/styles/components/{specialized → application-and-system}/_c8y-cookie-banner.scss +0 -0
  213. /package/styles/components/{specialized → application-and-system}/_c8y-login.scss +0 -0
  214. /package/styles/components/{specialized → data-display-and-visualization}/_c8y-data-explorer.scss +0 -0
  215. /package/styles/components/{specialized → data-display-and-visualization}/_c8y-datapoint-pill.scss +0 -0
  216. /package/styles/components/{specialized → data-display-and-visualization}/_c8y-pulse.scss +0 -0
  217. /package/styles/components/{specialized → data-display-and-visualization}/_smart-list-icon-label.scss +0 -0
  218. /package/styles/components/{specialized → data-display-and-visualization}/_status.scss +0 -0
  219. /package/styles/components/{specialized → data-display-and-visualization}/_statusContainer.scss +0 -0
  220. /package/styles/components/{specialized → data-input}/_c8y-countdown-interval.scss +0 -0
  221. /package/styles/components/{specialized → data-input}/_c8y-range.scss +0 -0
  222. /package/styles/components/{specialized → data-input}/_search-header.scss +0 -0
  223. /package/styles/components/{specialized → data-input}/_static-assets-file-picker.scss +0 -0
  224. /package/styles/components/{specialized → navigation-and-layout}/_c8y-role-card.scss +0 -0
  225. /package/styles/components/{specialized → navigation-and-layout}/_c8y-scrollbar.scss +0 -0
  226. /package/styles/components/{specialized → navigation-and-layout}/_c8y-smart-rest-tab.scss +0 -0
  227. /package/styles/components/{specialized → navigation-and-layout}/_c8y-stepper.scss +0 -0
  228. /package/styles/components/{specialized → navigation-and-layout}/_c8y-user-roles.scss +0 -0
  229. /package/styles/components/{specialized → navigation-and-layout}/_device-software-tab.scss +0 -0
  230. /package/styles/components/{specialized → status-feedback-and-notifications}/_c8y-message-banner.scss +0 -0
  231. /package/styles/components/{specialized → status-feedback-and-notifications}/_code.scss +0 -0
  232. /package/styles/mixins/{alert-variant.less → _alert-variant.less} +0 -0
  233. /package/styles/mixins/{animation.less → _animation.less} +0 -0
  234. /package/styles/mixins/{background-variant.less → _background-variant.less} +0 -0
  235. /package/styles/mixins/{border-radius.less → _border-radius.less} +0 -0
  236. /package/styles/mixins/{buttons.less → _buttons.less} +0 -0
  237. /package/styles/mixins/{c8y-scrollbar.less → _c8y-scrollbar.less} +0 -0
  238. /package/styles/mixins/{center-block.less → _center-block.less} +0 -0
  239. /package/styles/mixins/{clearfix.less → _clearfix.less} +0 -0
  240. /package/styles/mixins/{create-grid.less → _create-grid.less} +0 -0
  241. /package/styles/mixins/{grid.less → _grid.less} +0 -0
  242. /package/styles/mixins/{hide-scrollbars.less → _hide-scrollbars.less} +0 -0
  243. /package/styles/mixins/{hide-text.less → _hide-text.less} +0 -0
  244. /package/styles/mixins/{image.less → _image.less} +0 -0
  245. /package/styles/mixins/{labels.less → _labels.less} +0 -0
  246. /package/styles/mixins/{list-group.less → _list-group.less} +0 -0
  247. /package/styles/mixins/{nav-divider.less → _nav-divider.less} +0 -0
  248. /package/styles/mixins/{opacity.less → _opacity.less} +0 -0
  249. /package/styles/mixins/{pagination.less → _pagination.less} +0 -0
  250. /package/styles/mixins/{panels.less → _panels.less} +0 -0
  251. /package/styles/mixins/{reset-filter.less → _reset-filter.less} +0 -0
  252. /package/styles/mixins/{reset-text.less → _reset-text.less} +0 -0
  253. /package/styles/mixins/{resize.less → _resize.less} +0 -0
  254. /package/styles/mixins/{responsive-visibility.less → _responsive-visibility.less} +0 -0
  255. /package/styles/mixins/{size.less → _size.less} +0 -0
  256. /package/styles/mixins/{tab-focus.less → _tab-focus.less} +0 -0
  257. /package/styles/mixins/{table-row.less → _table-row.less} +0 -0
  258. /package/styles/mixins/{tag.less → _tag.less} +0 -0
  259. /package/styles/mixins/{text-emphasis.less → _text-emphasis.less} +0 -0
  260. /package/styles/mixins/{text-overflow.less → _text-overflow.less} +0 -0
  261. /package/variables/{login-vars.scss → _login-vars.scss} +0 -0
  262. /package/variables/{shadows.less → _shadows.less} +0 -0
  263. /package/variables/{shadows.scss → _shadows.scss} +0 -0
  264. /package/variables/tokens/{c8y-design-tokens-dark.scss → _c8y-design-tokens-dark.scss} +0 -0
  265. /package/variables/tokens/{c8y-design-tokens.scss → _c8y-design-tokens.scss} +0 -0
@@ -0,0 +1,512 @@
1
+ #!/bin/bash
2
+
3
+ # Semi-Automated SCSS → LESS Converter
4
+ # Converts SCSS syntax to LESS syntax with safety checks and manual review
5
+
6
+ set -e
7
+
8
+ # Get script directory for relative file paths
9
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10
+
11
+ # Colors for output
12
+ RED='\033[0;31m'
13
+ GREEN='\033[0;32m'
14
+ YELLOW='\033[1;33m'
15
+ BLUE='\033[0;34m'
16
+ NC='\033[0m' # No Color
17
+
18
+ # Flags
19
+ DRY_RUN=false
20
+ VERBOSE=false
21
+ AUTO_APPROVE=false
22
+ CONVERT_ALL=false
23
+
24
+ # Parse arguments
25
+ while [[ $# -gt 0 ]]; do
26
+ case $1 in
27
+ --dry-run)
28
+ DRY_RUN=true
29
+ shift
30
+ ;;
31
+ --verbose)
32
+ VERBOSE=true
33
+ shift
34
+ ;;
35
+ --yes|-y)
36
+ AUTO_APPROVE=true
37
+ shift
38
+ ;;
39
+ --all)
40
+ CONVERT_ALL=true
41
+ shift
42
+ ;;
43
+ --help|-h)
44
+ cat <<EOF
45
+ SCSS to LESS Converter
46
+
47
+ Usage: $0 [OPTIONS] [FILE]
48
+
49
+ Options:
50
+ --dry-run Show what would be converted without writing files
51
+ --verbose Show detailed conversion steps
52
+ --yes, -y Auto-approve all conversions (use with caution)
53
+ --all Convert all modified SCSS files
54
+ --help, -h Show this help message
55
+
56
+ Examples:
57
+ $0 styles/core/buttons/_buttons.scss
58
+ $0 --dry-run styles/core/forms/_forms.scss
59
+ $0 --all
60
+ $0 --yes --all
61
+
62
+ Note:
63
+ Variable imports are automatically removed from LESS files since LESS uses
64
+ global scope (variables imported at entry points are available everywhere).
65
+ This differs from SCSS's @use module system which requires explicit imports.
66
+
67
+ EOF
68
+ exit 0
69
+ ;;
70
+ *)
71
+ SCSS_FILE="$1"
72
+ shift
73
+ ;;
74
+ esac
75
+ done
76
+
77
+ # Function to print colored messages
78
+ print_info() {
79
+ echo -e "${BLUE}ℹ${NC} $1"
80
+ }
81
+
82
+ print_success() {
83
+ echo -e "${GREEN}✅${NC} $1"
84
+ }
85
+
86
+ print_warning() {
87
+ echo -e "${YELLOW}⚠️${NC} $1"
88
+ }
89
+
90
+ print_error() {
91
+ echo -e "${RED}❌${NC} $1"
92
+ }
93
+
94
+ # Function to convert SCSS syntax to LESS
95
+ convert_syntax() {
96
+ local content="$1"
97
+ local warnings=""
98
+
99
+ # Track complex patterns that need review
100
+ local needs_review=false
101
+
102
+ # 0a. Remove SCSS-specific @use imports FIRST (sass:string, sass:math, etc.)
103
+ if [[ $VERBOSE == true ]]; then
104
+ print_info "Removing SCSS-specific @use imports"
105
+ fi
106
+ content=$(echo "$content" | sed '/^@use[[:space:]]*["'"'"']sass:/d')
107
+
108
+ # 0b. Convert string.unquote() to ~'' BEFORE other conversions
109
+ if [[ $VERBOSE == true ]]; then
110
+ print_info "Converting string.unquote() → ~''"
111
+ fi
112
+ # Handle single quotes
113
+ content=$(echo "$content" | sed -E "s/string\.unquote\('([^']+)'\)/~'\1'/g")
114
+ # Handle double quotes
115
+ content=$(echo "$content" | sed -E "s/string\.unquote\(\"([^\"]+)\"\)/~\"\1\"/g")
116
+
117
+ # 0b2. Convert math.div(a, b) to (a / b) BEFORE other conversions
118
+ if [[ $VERBOSE == true ]]; then
119
+ print_info "Converting math.div() → (a / b)"
120
+ fi
121
+ content=$(echo "$content" | sed -E 's/math\.div\(([^,]+),([^)]+)\)/(\1 \/\2)/g')
122
+
123
+ # 0c. Convert @use to @import (remove 'as *' and add .less extension)
124
+ if [[ $VERBOSE == true ]]; then
125
+ print_info "Converting @use → @import"
126
+ fi
127
+ # With 'as *' suffix - double quotes
128
+ content=$(echo "$content" | sed -E 's/@use +"([^"]+)" +as +\*;/@import "\1";/g')
129
+ # With 'as *' suffix - single quotes
130
+ content=$(echo "$content" | sed -E "s/@use +'([^']+)' +as +\*;/@import '\1';/g")
131
+ # Without 'as *' - double quotes
132
+ content=$(echo "$content" | sed -E 's/@use +"([^"]+)";/@import "\1";/g')
133
+ # Without 'as *' - single quotes
134
+ content=$(echo "$content" | sed -E "s/@use +'([^']+)';/@import '\1';/g")
135
+
136
+ # 0d. Add underscore prefix and .less extension to @import paths
137
+ # SCSS allows omitting _ and extension, LESS requires exact filenames
138
+ if [[ $VERBOSE == true ]]; then
139
+ print_info "Normalizing @import paths for LESS"
140
+ fi
141
+ # Process @import statements with path/filename pattern
142
+ # Add _ prefix if filename doesn't start with _ (unless it's index)
143
+ # Add .less extension if not present
144
+ # IMPORTANT: Anchor to start of line to avoid matching quoted strings in CSS properties
145
+ content=$(echo "$content" | perl -pe '
146
+ s{^\s*\@import\s+(["'\''])([^"'\'']*/)([^_/][^"'\''/]+?)["'\'']}{
147
+ my ($quote, $path, $file) = ($1, $2, $3);
148
+ $file = "_$file" unless $file =~ /^index$/;
149
+ $file .= ".less" unless $file =~ /\.less$/;
150
+ "\@import $quote$path$file$quote"
151
+ }gme;
152
+ s{^\s*\@import\s+(["'\''])([^/]+?)["'\'']}{
153
+ my ($quote, $file) = ($1, $2);
154
+ $file = "_$file" unless $file =~ /^_/ or $file =~ /^index$/;
155
+ $file .= ".less" unless $file =~ /\.less$/;
156
+ "\@import $quote$file$quote"
157
+ }gme;
158
+ ')
159
+ # Add .less extension to imports that already have _ but no extension
160
+ content=$(echo "$content" | sed -E "s/@import (['\"])(_[^'\"]+)(['\"])/\@import \1\2.less\3/g")
161
+ # Fix double .less.less
162
+ content=$(echo "$content" | sed -E 's/\.less\.less/.less/g')
163
+
164
+ # 0e. Remove redundant variable imports (LESS has global scope)
165
+ # Variables are imported at entry points (main.less, branding.less, login.less), so component
166
+ # files don't need to re-import them. This is different from SCSS @use which requires
167
+ # explicit imports due to its module system.
168
+ if [[ $VERBOSE == true ]]; then
169
+ print_info "Removing redundant variable imports (LESS has global scope)"
170
+ fi
171
+ # Remove any import of variables/index.less or _login-vars.less
172
+ content=$(echo "$content" | sed -E '/@import[[:space:]]+.*variables\/index\.less/d')
173
+ content=$(echo "$content" | sed -E '/@import[[:space:]]+.*variables\/_login-vars\.less/d')
174
+
175
+ # 1. Remove @content keyword (LESS doesn't support it)
176
+ # Mixins with @content need manual expansion - just remove the keyword itself
177
+ if echo "$content" | grep -q "@content"; then
178
+ if [[ $VERBOSE == true ]]; then
179
+ print_info "Removing @content keywords (not supported in LESS)"
180
+ fi
181
+ # Simply remove @content; lines - the mixin caller still needs manual work
182
+ content=$(echo "$content" | sed '/^[[:space:]]*@content;*$/d')
183
+ warnings="${warnings}⚠️ @content removed - mixins need manual handling in LESS\n"
184
+ needs_review=true
185
+ fi
186
+
187
+ # 2. Convert mixin definitions (before converting variables): @mixin name() → .name()
188
+ if [[ $VERBOSE == true ]]; then
189
+ print_info "Converting mixin definitions: @mixin → .name()"
190
+ fi
191
+ content=$(echo "$content" | sed -E 's/@mixin[[:space:]]+([a-zA-Z0-9_-]+)/.\1/g')
192
+
193
+ # 2. Remove SCSS module namespacing BEFORE converting @include
194
+ if [[ $VERBOSE == true ]]; then
195
+ print_info "Removing module namespacing"
196
+ fi
197
+ # Remove module prefix before dollar signs (variables): module.$var → $var
198
+ content=$(echo "$content" | sed -E 's/[a-zA-Z0-9_-]+\.\$/\$/g')
199
+ # Remove module prefix for mixin calls: @include module.mixin() → @include mixin()
200
+ content=$(echo "$content" | sed -E 's/@include +[a-zA-Z0-9_-]+\.([a-zA-Z0-9_-]+)/@include \1/g')
201
+
202
+ # 2b. Convert mixin includes: @include mixin() → .mixin()
203
+ if [[ $VERBOSE == true ]]; then
204
+ print_info "Converting mixin calls: @include → .mixin()"
205
+ fi
206
+ content=$(echo "$content" | sed -E 's/@include[[:space:]]+([a-zA-Z0-9_-]+)/.\1/g')
207
+
208
+ # Note: Mixin calls without parentheses will generate LESS deprecated warnings
209
+ # These should be manually fixed in LESS files after conversion
210
+ # Automatic conversion is too error-prone (matches decimals, @content, etc.)
211
+
212
+ # 3. Convert variables: $var → @var (after mixins so @mixin doesn't become @.ixin)
213
+ if [[ $VERBOSE == true ]]; then
214
+ print_info "Converting variables: \$var → @var"
215
+ fi
216
+ content=$(echo "$content" | sed -E 's/\$([a-zA-Z0-9_-]+)/@\1/g')
217
+
218
+ # 4. Convert interpolation: #{$var} → @{var}
219
+ if [[ $VERBOSE == true ]]; then
220
+ print_info "Converting interpolation: #{} → @{}"
221
+ fi
222
+ content=$(echo "$content" | sed -E 's/#\{@([a-zA-Z0-9_-]+)\}/@{\1}/g')
223
+
224
+ # 5. Convert mixin parameter separators: commas → semicolons (LESS prefers semicolons)
225
+ # IMPORTANT: Only convert commas that are clearly inside mixin definitions/calls, not selector commas
226
+ if [[ $VERBOSE == true ]]; then
227
+ print_info "Converting mixin parameter separators: , → ; (in mixin definitions/calls only)"
228
+ fi
229
+
230
+ # Strategy: Convert commas to semicolons ONLY in mixin definitions/calls
231
+ # This specifically targets mixin parameter lists: .mixin(@param1, @param2, @param3)
232
+ # But PRESERVES commas in CSS function calls: transform: translate(@x, @y)
233
+ #
234
+ # Key distinction:
235
+ # - Mixin definitions/calls: .name(@params) or lines starting with .
236
+ # - CSS property values: lines with property: value pattern
237
+ #
238
+ # Solution: Only convert commas on lines that start with . (mixin definitions/calls)
239
+ # This reliably identifies mixin contexts and avoids CSS property values
240
+
241
+ # Process line by line to have better context control
242
+ content=$(echo "$content" | perl -pe '
243
+ # Only process lines that start with . (after optional whitespace) - these are mixin definitions/calls
244
+ if (/^\s*\./) {
245
+ # On mixin definition/call lines, convert comma-before-@variable to semicolon-before-@variable
246
+ # This simpler pattern works even when default values contain commas (like rgba())
247
+ # because we only care about commas that are directly followed by @variable names
248
+ s/,(\s*@[a-zA-Z0-9_-]+)/;$1/g;
249
+ }
250
+ ')
251
+
252
+ # Check if we converted @use
253
+ if echo "$content" | grep -q "@import.*\.less"; then
254
+ warnings="${warnings}⚠️ @use converted to @import - review if needed\n"
255
+ fi
256
+
257
+ # 6. Convert @forward to @import
258
+ if echo "$content" | grep -q "@forward "; then
259
+ if [[ $VERBOSE == true ]]; then
260
+ print_info "Converting @forward → @import"
261
+ fi
262
+ content=$(echo "$content" | sed -E "s/@forward[[:space:]]+(['\"])([^'\"]+)\\1/@import \\1\\2\\1/g")
263
+ warnings="${warnings}⚠️ @forward converted to @import - review re-exports\n"
264
+ needs_review=true
265
+ fi
266
+
267
+ # 7. Flag complex color functions for review
268
+ if echo "$content" | grep -qE "rgba\(@[a-zA-Z0-9_-]+,[[:space:]]*0\.[0-9]+\)"; then
269
+ warnings="${warnings}⚠️ rgba() with alpha detected - consider using fade() in LESS\n"
270
+ needs_review=true
271
+ fi
272
+
273
+ # 8. Convert @extend to LESS :extend() syntax
274
+ # SCSS: @extend .class !optional;
275
+ # LESS: &:extend(.class);
276
+ if echo "$content" | grep -q "@extend "; then
277
+ if [[ $VERBOSE == true ]]; then
278
+ print_info "Converting @extend → &:extend()"
279
+ fi
280
+ # Convert @extend .class !optional; to &:extend(.class);
281
+ content=$(echo "$content" | sed -E 's/^([[:space:]]*)@extend[[:space:]]+\.([a-zA-Z0-9_-]+)[[:space:]]+!optional;/\1\&:extend(.\2);/g')
282
+ # Convert @extend .class; to &:extend(.class);
283
+ content=$(echo "$content" | sed -E 's/^([[:space:]]*)@extend[[:space:]]+\.([a-zA-Z0-9_-]+);/\1\&:extend(.\2);/g')
284
+ # Convert @extend class !optional; to &:extend(.class); (for classes without dot)
285
+ content=$(echo "$content" | sed -E 's/^([[:space:]]*)@extend[[:space:]]+([a-zA-Z0-9_-]+)[[:space:]]+!optional;/\1\&:extend(.\2);/g')
286
+ warnings="${warnings}⚠️ @extend converted to :extend() - review output\n"
287
+ fi
288
+
289
+ # 9. Convert @if/@else to LESS guards
290
+ # SCSS: @if $var == value { ... } @else if $var == value2 { ... } @else { ... }
291
+ # LESS: & when (@var = value) { ... } & when (@var = value2) { ... } & when (default()) { ... }
292
+ if echo "$content" | grep -qE "@if |@else"; then
293
+ if [[ $VERBOSE == true ]]; then
294
+ print_info "Converting @if/@else → LESS guards"
295
+ fi
296
+
297
+ # Convert @else if to & when (note: after variable conversion $ → @)
298
+ content=$(echo "$content" | sed -E 's/^([[:space:]]*)} @else if ([^{]+)\{/\1}\n\1\& when (\2) {/g')
299
+
300
+ # Convert @if var != '' to & when not (var = ~'') BEFORE generic @if conversion
301
+ content=$(echo "$content" | sed -E "s/^([[:space:]]*)@if ([^ ]+) != '' \{/\1\& when not (\2 = ~'') {/g")
302
+ content=$(echo "$content" | sed -E 's/^([[:space:]]*)@if ([^ ]+) != "" \{/\1\& when not (\2 = ~"") {/g')
303
+
304
+ # Convert standalone @if to & when
305
+ content=$(echo "$content" | sed -E 's/^([[:space:]]*)@if ([^{]+)\{/\1\& when (\2) {/g')
306
+
307
+ # Convert @else { to & when (default()) {
308
+ content=$(echo "$content" | sed -E 's/^([[:space:]]*)} @else \{/\1}\n\1\& when (default()) {/g')
309
+
310
+ # Convert == to = in guards (LESS uses single =)
311
+ content=$(echo "$content" | sed -E 's/& when \(([^)]*) == /\& when (\1 = /g')
312
+
313
+ # Add comment about guard conversion
314
+ warnings="${warnings}⚠️ @if/@else converted to LESS guards - review conditional logic\n"
315
+ needs_review=true
316
+ fi
317
+
318
+ # Return results via file (since we can't return complex data from bash function)
319
+ echo "$content" > /tmp/scss-less-convert-content.tmp
320
+ echo -e "$warnings" > /tmp/scss-less-convert-warnings.tmp
321
+ if [[ $needs_review == true ]]; then
322
+ echo "1" > /tmp/scss-less-convert-needsreview.tmp
323
+ else
324
+ echo "0" > /tmp/scss-less-convert-needsreview.tmp
325
+ fi
326
+ }
327
+
328
+ # Function to convert a single file
329
+ convert_file() {
330
+ local scss_file="$1"
331
+
332
+ # Strip packages/style/ prefix if present
333
+ scss_file="${scss_file#packages/style/}"
334
+
335
+ # Check skip list for files that need manual conversion
336
+ if [[ -f "$SCRIPT_DIR/scss-to-less-skip" ]]; then
337
+ if grep -q "^${scss_file}$" "$SCRIPT_DIR/scss-to-less-skip" 2>/dev/null; then
338
+ print_warning "Skipping $scss_file (in skip list - requires manual sync)"
339
+ return 0
340
+ fi
341
+ fi
342
+
343
+ # Special case: stroke icons file uses a different conversion process
344
+ if [[ "$scss_file" == *"_dlt-c8y-icons-stroke.scss" ]]; then
345
+ print_info "Converting stroke icons file (uses special converter)"
346
+ if [[ $DRY_RUN == false ]]; then
347
+ node "$SCRIPT_DIR/convert-stroke-icons-to-less.js"
348
+ print_success "Stroke icons converted successfully"
349
+ else
350
+ print_info "Dry run - would run: node $SCRIPT_DIR/convert-stroke-icons-to-less.js"
351
+ fi
352
+ return 0
353
+ fi
354
+
355
+ # Check if file exists (may be a renamed/deleted file from git diff)
356
+ if [[ ! -f "$scss_file" ]]; then
357
+ print_warning "Skipping $scss_file (file not found - may have been renamed/deleted)"
358
+ return 0
359
+ fi
360
+
361
+ # Determine LESS file path
362
+ local less_file="${scss_file%.scss}.less"
363
+
364
+ if [[ ! -f "$less_file" ]]; then
365
+ print_warning "Skipping $scss_file (no corresponding LESS file: $less_file)"
366
+ return 0
367
+ fi
368
+
369
+ print_info "Converting: $scss_file → $less_file"
370
+
371
+ # Read SCSS content
372
+ local scss_content=$(cat "$scss_file")
373
+
374
+ # Convert syntax
375
+ convert_syntax "$scss_content"
376
+
377
+ # Read results
378
+ local less_content=$(cat /tmp/scss-less-convert-content.tmp)
379
+ local warnings=$(cat /tmp/scss-less-convert-warnings.tmp)
380
+ local needs_review=$(cat /tmp/scss-less-convert-needsreview.tmp)
381
+
382
+ # Clean up temp files
383
+ rm -f /tmp/scss-less-convert-content.tmp /tmp/scss-less-convert-warnings.tmp /tmp/scss-less-convert-needsreview.tmp
384
+
385
+ # Show warnings if any
386
+ if [[ -n "$warnings" && "$warnings" != "" ]]; then
387
+ echo ""
388
+ echo -e "$warnings"
389
+ fi
390
+
391
+ # Create temp file with new content
392
+ echo "$less_content" > /tmp/scss-less-new-content.tmp
393
+
394
+ # Show diff
395
+ echo ""
396
+ print_info "Changes to be applied:"
397
+ echo ""
398
+
399
+ # Create a colored diff
400
+ if command -v colordiff >/dev/null 2>&1; then
401
+ diff -u "$less_file" /tmp/scss-less-new-content.tmp | colordiff || true
402
+ else
403
+ diff -u "$less_file" /tmp/scss-less-new-content.tmp || true
404
+ fi
405
+
406
+ echo ""
407
+
408
+ # Check if there are actual changes
409
+ if diff -q "$less_file" /tmp/scss-less-new-content.tmp >/dev/null 2>&1; then
410
+ print_success "No changes needed - files already in sync"
411
+ rm /tmp/scss-less-new-content.tmp
412
+ return 0
413
+ fi
414
+
415
+ # Ask for confirmation (unless dry-run or auto-approve)
416
+ if [[ $DRY_RUN == true ]]; then
417
+ print_info "Dry run - no files modified"
418
+ rm /tmp/scss-less-new-content.tmp
419
+ return 0
420
+ fi
421
+
422
+ if [[ $AUTO_APPROVE == false ]]; then
423
+ if [[ $needs_review == "1" ]]; then
424
+ print_warning "Complex patterns detected - manual review recommended"
425
+ fi
426
+
427
+ echo -n "Apply these changes to $less_file? [y/N] "
428
+ read -r response
429
+
430
+ if [[ ! "$response" =~ ^[Yy]$ ]]; then
431
+ print_info "Skipped - no changes made"
432
+ rm /tmp/scss-less-new-content.tmp
433
+ return 0
434
+ fi
435
+ fi
436
+
437
+ # Apply changes
438
+ mv /tmp/scss-less-new-content.tmp "$less_file"
439
+ print_success "Converted: $less_file"
440
+
441
+ return 0
442
+ }
443
+
444
+ # Main execution
445
+ echo "==========================================="
446
+ echo "SCSS → LESS Semi-Automated Converter"
447
+ echo "==========================================="
448
+ echo ""
449
+
450
+ if [[ $CONVERT_ALL == true ]]; then
451
+ # Convert all modified SCSS files
452
+ print_info "Finding all modified SCSS files..."
453
+
454
+ SCSS_FILES=$(git diff --name-only HEAD -- . | grep '\.scss$' || true)
455
+ SCSS_STAGED=$(git diff --cached --name-only -- . | grep '\.scss$' || true)
456
+ ALL_SCSS=$(printf "%s\n%s" "$SCSS_FILES" "$SCSS_STAGED" | sort -u | grep -v '^$' || true)
457
+
458
+ if [[ -z "$ALL_SCSS" ]]; then
459
+ print_success "No modified SCSS files found"
460
+ exit 0
461
+ fi
462
+
463
+ SCSS_COUNT=$(echo "$ALL_SCSS" | wc -l | tr -d ' ')
464
+ print_info "Found $SCSS_COUNT modified SCSS file(s)"
465
+ echo ""
466
+
467
+ SUCCESS_COUNT=0
468
+ SKIP_COUNT=0
469
+ ERROR_COUNT=0
470
+
471
+ while IFS= read -r file; do
472
+ if [[ -z "$file" ]]; then
473
+ continue
474
+ fi
475
+
476
+ if convert_file "$file"; then
477
+ SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
478
+ else
479
+ ERROR_COUNT=$((ERROR_COUNT + 1))
480
+ fi
481
+
482
+ echo ""
483
+ done <<< "$ALL_SCSS"
484
+
485
+ echo "==========================================="
486
+ print_info "Conversion Summary:"
487
+ print_success "$SUCCESS_COUNT file(s) converted"
488
+ if [[ $ERROR_COUNT -gt 0 ]]; then
489
+ print_error "$ERROR_COUNT file(s) failed"
490
+ fi
491
+ echo "==========================================="
492
+
493
+ exit 0
494
+
495
+ elif [[ -n "$SCSS_FILE" ]]; then
496
+ # Convert single file
497
+ if convert_file "$SCSS_FILE"; then
498
+ exit 0
499
+ else
500
+ exit 1
501
+ fi
502
+
503
+ else
504
+ # No file specified
505
+ print_error "No file specified"
506
+ echo ""
507
+ echo "Usage: $0 [OPTIONS] <scss-file>"
508
+ echo " $0 --all"
509
+ echo ""
510
+ echo "Use --help for more options"
511
+ exit 1
512
+ fi
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Convert SCSS stroke icons file to LESS
5
+ *
6
+ * The SCSS version uses SCSS maps and map.get() which LESS doesn't support.
7
+ * This script converts it to direct LESS class definitions.
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+
13
+ const scssFile = path.join(__dirname, 'styles/icons/_dlt-c8y-icons-stroke.scss');
14
+ const lessFile = path.join(__dirname, 'styles/icons/_dlt-c8y-icons-stroke.less');
15
+
16
+ console.log('Converting SCSS stroke icons to LESS...');
17
+
18
+ // Read SCSS file
19
+ const scssContent = fs.readFileSync(scssFile, 'utf8');
20
+
21
+ // Extract the icon map
22
+ const mapMatch = scssContent.match(/\$dlt-c8y-icons:\s*\(([\s\S]*?)\);/);
23
+ if (!mapMatch) {
24
+ console.error('Could not find icon map in SCSS file');
25
+ process.exit(1);
26
+ }
27
+
28
+ // Parse the map entries
29
+ const mapContent = mapMatch[1];
30
+ const iconEntries = [];
31
+ const lines = mapContent.split('\n');
32
+
33
+ for (const line of lines) {
34
+ const match = line.match(/['"]([^'"]+)['"]\s*:\s*["']([^"']+)["']/);
35
+ if (match) {
36
+ iconEntries.push({
37
+ name: match[1],
38
+ unicode: match[2]
39
+ });
40
+ }
41
+ }
42
+
43
+ console.log(`Found ${iconEntries.length} icon entries in map`);
44
+
45
+ // Extract all icon-stroke mixin calls to get the complete list
46
+ const mixinCalls = [];
47
+ const mixinCallRegex = /@include icon-stroke\(['"]([^'"]+)['"]\);/g;
48
+ let match;
49
+ while ((match = mixinCallRegex.exec(scssContent)) !== null) {
50
+ mixinCalls.push(match[1]);
51
+ }
52
+
53
+ console.log(`Found ${mixinCalls.length} mixin calls`);
54
+
55
+ // Create a map for quick lookup
56
+ const iconMap = new Map();
57
+ for (const entry of iconEntries) {
58
+ iconMap.set(entry.name, entry.unicode);
59
+ }
60
+
61
+ // Generate LESS content
62
+ let lessContent = `@import "../../variables/index.less";
63
+
64
+ /**
65
+ * DLT C8Y Icons Stroke - Stroked icon definitions (GENERATED FILE)
66
+ *
67
+ * Note: This file is auto-generated from the SCSS version by convert-stroke-icons-to-less.js
68
+ * DO NOT EDIT MANUALLY - Changes will be overwritten
69
+ *
70
+ * Intentionally hardcoded values:
71
+ * - Stroke width (2px): Icon stroke rendering
72
+ * - Unicode icon codes: Icon font character mappings
73
+ */
74
+
75
+ // Stroked icon styles - CONVERTED FROM SCSS
76
+ // Auto-converted from _dlt-c8y-icons-stroke.scss
77
+ // DO NOT EDIT MANUALLY - Run 'node convert-stroke-icons-to-less.js' to regenerate
78
+
79
+ // Base stroked-icon styles (applies to all icons with .stroked-icon class)
80
+ [class^='dlt-c8y-icon-'],
81
+ [class*=' dlt-c8y-icon-'] {
82
+ &.stroked-icon {
83
+ position: relative;
84
+ z-index: 0;
85
+
86
+ &::before {
87
+ position: absolute;
88
+ -webkit-text-stroke-width: 2px;
89
+ -webkit-text-stroke-color: var(--c8y-icon-stroke-color, @component-background-default);
90
+ }
91
+
92
+ &::after {
93
+ position: relative;
94
+ }
95
+ }
96
+ }
97
+
98
+ // Individual icon definitions
99
+ `;
100
+
101
+ // Generate class definitions for each icon
102
+ for (const iconName of mixinCalls) {
103
+ const unicode = iconMap.get(iconName);
104
+ if (unicode) {
105
+ lessContent += `.${iconName}.stroked-icon::after {\n content: "${unicode}";\n}\n\n`;
106
+ } else {
107
+ console.warn(`Warning: No unicode value found for ${iconName}`);
108
+ }
109
+ }
110
+
111
+ // Write LESS file
112
+ fs.writeFileSync(lessFile, lessContent, 'utf8');
113
+
114
+ console.log(`✅ Successfully converted to ${lessFile}`);
115
+ console.log(` Generated ${mixinCalls.length} icon class definitions`);