@dazl/shorthands-opener 4.2.0

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 (237) hide show
  1. package/README.md +3 -0
  2. package/dist/compounds/compound-css-data.d.ts +22 -0
  3. package/dist/compounds/compound-css-data.d.ts.map +1 -0
  4. package/dist/compounds/compound-css-data.js +2 -0
  5. package/dist/compounds/compound-css-data.js.map +1 -0
  6. package/dist/compounds/compound-mapper.d.ts +4 -0
  7. package/dist/compounds/compound-mapper.d.ts.map +1 -0
  8. package/dist/compounds/compound-mapper.js +10 -0
  9. package/dist/compounds/compound-mapper.js.map +1 -0
  10. package/dist/compounds/compound-parser-utils.d.ts +3 -0
  11. package/dist/compounds/compound-parser-utils.d.ts.map +1 -0
  12. package/dist/compounds/compound-parser-utils.js +33 -0
  13. package/dist/compounds/compound-parser-utils.js.map +1 -0
  14. package/dist/compounds/compound-types.d.ts +26 -0
  15. package/dist/compounds/compound-types.d.ts.map +1 -0
  16. package/dist/compounds/compound-types.js +2 -0
  17. package/dist/compounds/compound-types.js.map +1 -0
  18. package/dist/compounds/compound-value-parsers.d.ts +6 -0
  19. package/dist/compounds/compound-value-parsers.d.ts.map +1 -0
  20. package/dist/compounds/compound-value-parsers.js +5 -0
  21. package/dist/compounds/compound-value-parsers.js.map +1 -0
  22. package/dist/compounds/index.d.ts +6 -0
  23. package/dist/compounds/index.d.ts.map +1 -0
  24. package/dist/compounds/index.js +6 -0
  25. package/dist/compounds/index.js.map +1 -0
  26. package/dist/compounds/parsers/index.d.ts +2 -0
  27. package/dist/compounds/parsers/index.d.ts.map +1 -0
  28. package/dist/compounds/parsers/index.js +2 -0
  29. package/dist/compounds/parsers/index.js.map +1 -0
  30. package/dist/compounds/parsers/shadow-compound.d.ts +5 -0
  31. package/dist/compounds/parsers/shadow-compound.d.ts.map +1 -0
  32. package/dist/compounds/parsers/shadow-compound.js +39 -0
  33. package/dist/compounds/parsers/shadow-compound.js.map +1 -0
  34. package/dist/css-data-types/data-types-consts.d.ts +212 -0
  35. package/dist/css-data-types/data-types-consts.d.ts.map +1 -0
  36. package/dist/css-data-types/data-types-consts.js +790 -0
  37. package/dist/css-data-types/data-types-consts.js.map +1 -0
  38. package/dist/css-data-types/data-types-predicates.d.ts +32 -0
  39. package/dist/css-data-types/data-types-predicates.d.ts.map +1 -0
  40. package/dist/css-data-types/data-types-predicates.js +353 -0
  41. package/dist/css-data-types/data-types-predicates.js.map +1 -0
  42. package/dist/css-data-types/data-types-state-machines.d.ts +14 -0
  43. package/dist/css-data-types/data-types-state-machines.d.ts.map +1 -0
  44. package/dist/css-data-types/data-types-state-machines.js +129 -0
  45. package/dist/css-data-types/data-types-state-machines.js.map +1 -0
  46. package/dist/css-data-types/data-types-types.d.ts +26 -0
  47. package/dist/css-data-types/data-types-types.d.ts.map +1 -0
  48. package/dist/css-data-types/data-types-types.js +2 -0
  49. package/dist/css-data-types/data-types-types.js.map +1 -0
  50. package/dist/css-data-types/data-types-utils.d.ts +31 -0
  51. package/dist/css-data-types/data-types-utils.d.ts.map +1 -0
  52. package/dist/css-data-types/data-types-utils.js +176 -0
  53. package/dist/css-data-types/data-types-utils.js.map +1 -0
  54. package/dist/css-data-types/data-types.d.ts +64 -0
  55. package/dist/css-data-types/data-types.d.ts.map +1 -0
  56. package/dist/css-data-types/data-types.js +304 -0
  57. package/dist/css-data-types/data-types.js.map +1 -0
  58. package/dist/css-data-types/index.d.ts +7 -0
  59. package/dist/css-data-types/index.d.ts.map +1 -0
  60. package/dist/css-data-types/index.js +7 -0
  61. package/dist/css-data-types/index.js.map +1 -0
  62. package/dist/index.d.ts +5 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +5 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/shorthands/index.d.ts +8 -0
  67. package/dist/shorthands/index.d.ts.map +1 -0
  68. package/dist/shorthands/index.js +8 -0
  69. package/dist/shorthands/index.js.map +1 -0
  70. package/dist/shorthands/openers/background-position-shorthand.d.ts +5 -0
  71. package/dist/shorthands/openers/background-position-shorthand.d.ts.map +1 -0
  72. package/dist/shorthands/openers/background-position-shorthand.js +173 -0
  73. package/dist/shorthands/openers/background-position-shorthand.js.map +1 -0
  74. package/dist/shorthands/openers/background-shorthand.d.ts +5 -0
  75. package/dist/shorthands/openers/background-shorthand.d.ts.map +1 -0
  76. package/dist/shorthands/openers/background-shorthand.js +88 -0
  77. package/dist/shorthands/openers/background-shorthand.js.map +1 -0
  78. package/dist/shorthands/openers/border-image-shorthand.d.ts +5 -0
  79. package/dist/shorthands/openers/border-image-shorthand.d.ts.map +1 -0
  80. package/dist/shorthands/openers/border-image-shorthand.js +16 -0
  81. package/dist/shorthands/openers/border-image-shorthand.js.map +1 -0
  82. package/dist/shorthands/openers/border-radius-shorthand.d.ts +5 -0
  83. package/dist/shorthands/openers/border-radius-shorthand.d.ts.map +1 -0
  84. package/dist/shorthands/openers/border-radius-shorthand.js +61 -0
  85. package/dist/shorthands/openers/border-radius-shorthand.js.map +1 -0
  86. package/dist/shorthands/openers/border-shorthand.d.ts +20 -0
  87. package/dist/shorthands/openers/border-shorthand.d.ts.map +1 -0
  88. package/dist/shorthands/openers/border-shorthand.js +90 -0
  89. package/dist/shorthands/openers/border-shorthand.js.map +1 -0
  90. package/dist/shorthands/openers/flex-flow-shorthand.d.ts +5 -0
  91. package/dist/shorthands/openers/flex-flow-shorthand.d.ts.map +1 -0
  92. package/dist/shorthands/openers/flex-flow-shorthand.js +13 -0
  93. package/dist/shorthands/openers/flex-flow-shorthand.js.map +1 -0
  94. package/dist/shorthands/openers/flex-shorthand.d.ts +5 -0
  95. package/dist/shorthands/openers/flex-shorthand.d.ts.map +1 -0
  96. package/dist/shorthands/openers/flex-shorthand.js +55 -0
  97. package/dist/shorthands/openers/flex-shorthand.js.map +1 -0
  98. package/dist/shorthands/openers/font-shorthand.d.ts +5 -0
  99. package/dist/shorthands/openers/font-shorthand.d.ts.map +1 -0
  100. package/dist/shorthands/openers/font-shorthand.js +60 -0
  101. package/dist/shorthands/openers/font-shorthand.js.map +1 -0
  102. package/dist/shorthands/openers/gap-shorthand.d.ts +5 -0
  103. package/dist/shorthands/openers/gap-shorthand.d.ts.map +1 -0
  104. package/dist/shorthands/openers/gap-shorthand.js +28 -0
  105. package/dist/shorthands/openers/gap-shorthand.js.map +1 -0
  106. package/dist/shorthands/openers/grid-axis-shorthand.d.ts +6 -0
  107. package/dist/shorthands/openers/grid-axis-shorthand.d.ts.map +1 -0
  108. package/dist/shorthands/openers/grid-axis-shorthand.js +36 -0
  109. package/dist/shorthands/openers/grid-axis-shorthand.js.map +1 -0
  110. package/dist/shorthands/openers/grid-gap-shorthand.d.ts +5 -0
  111. package/dist/shorthands/openers/grid-gap-shorthand.d.ts.map +1 -0
  112. package/dist/shorthands/openers/grid-gap-shorthand.js +21 -0
  113. package/dist/shorthands/openers/grid-gap-shorthand.js.map +1 -0
  114. package/dist/shorthands/openers/grid-shorthand.d.ts +8 -0
  115. package/dist/shorthands/openers/grid-shorthand.d.ts.map +1 -0
  116. package/dist/shorthands/openers/grid-shorthand.js +145 -0
  117. package/dist/shorthands/openers/grid-shorthand.js.map +1 -0
  118. package/dist/shorthands/openers/grid-template-shorthand.d.ts +10 -0
  119. package/dist/shorthands/openers/grid-template-shorthand.d.ts.map +1 -0
  120. package/dist/shorthands/openers/grid-template-shorthand.js +113 -0
  121. package/dist/shorthands/openers/grid-template-shorthand.js.map +1 -0
  122. package/dist/shorthands/openers/index.d.ts +22 -0
  123. package/dist/shorthands/openers/index.d.ts.map +1 -0
  124. package/dist/shorthands/openers/index.js +22 -0
  125. package/dist/shorthands/openers/index.js.map +1 -0
  126. package/dist/shorthands/openers/list-style-shorthand.d.ts +5 -0
  127. package/dist/shorthands/openers/list-style-shorthand.d.ts.map +1 -0
  128. package/dist/shorthands/openers/list-style-shorthand.js +15 -0
  129. package/dist/shorthands/openers/list-style-shorthand.js.map +1 -0
  130. package/dist/shorthands/openers/margin-shorthand.d.ts +5 -0
  131. package/dist/shorthands/openers/margin-shorthand.d.ts.map +1 -0
  132. package/dist/shorthands/openers/margin-shorthand.js +11 -0
  133. package/dist/shorthands/openers/margin-shorthand.js.map +1 -0
  134. package/dist/shorthands/openers/outline-shorthand.d.ts +5 -0
  135. package/dist/shorthands/openers/outline-shorthand.d.ts.map +1 -0
  136. package/dist/shorthands/openers/outline-shorthand.js +14 -0
  137. package/dist/shorthands/openers/outline-shorthand.js.map +1 -0
  138. package/dist/shorthands/openers/overflow-shorthand.d.ts +5 -0
  139. package/dist/shorthands/openers/overflow-shorthand.d.ts.map +1 -0
  140. package/dist/shorthands/openers/overflow-shorthand.js +21 -0
  141. package/dist/shorthands/openers/overflow-shorthand.js.map +1 -0
  142. package/dist/shorthands/openers/padding-shorthand.d.ts +5 -0
  143. package/dist/shorthands/openers/padding-shorthand.d.ts.map +1 -0
  144. package/dist/shorthands/openers/padding-shorthand.js +11 -0
  145. package/dist/shorthands/openers/padding-shorthand.js.map +1 -0
  146. package/dist/shorthands/openers/place-content-shorthand.d.ts +5 -0
  147. package/dist/shorthands/openers/place-content-shorthand.d.ts.map +1 -0
  148. package/dist/shorthands/openers/place-content-shorthand.js +29 -0
  149. package/dist/shorthands/openers/place-content-shorthand.js.map +1 -0
  150. package/dist/shorthands/openers/place-items-shorthand.d.ts +5 -0
  151. package/dist/shorthands/openers/place-items-shorthand.d.ts.map +1 -0
  152. package/dist/shorthands/openers/place-items-shorthand.js +23 -0
  153. package/dist/shorthands/openers/place-items-shorthand.js.map +1 -0
  154. package/dist/shorthands/openers/text-decoration-shorthand.d.ts +5 -0
  155. package/dist/shorthands/openers/text-decoration-shorthand.d.ts.map +1 -0
  156. package/dist/shorthands/openers/text-decoration-shorthand.js +14 -0
  157. package/dist/shorthands/openers/text-decoration-shorthand.js.map +1 -0
  158. package/dist/shorthands/shorthand-css-data.d.ts +120 -0
  159. package/dist/shorthands/shorthand-css-data.d.ts.map +1 -0
  160. package/dist/shorthands/shorthand-css-data.js +48 -0
  161. package/dist/shorthands/shorthand-css-data.js.map +1 -0
  162. package/dist/shorthands/shorthand-mapper.d.ts +6 -0
  163. package/dist/shorthands/shorthand-mapper.d.ts.map +1 -0
  164. package/dist/shorthands/shorthand-mapper.js +72 -0
  165. package/dist/shorthands/shorthand-mapper.js.map +1 -0
  166. package/dist/shorthands/shorthand-parser-errors.d.ts +25 -0
  167. package/dist/shorthands/shorthand-parser-errors.d.ts.map +1 -0
  168. package/dist/shorthands/shorthand-parser-errors.js +41 -0
  169. package/dist/shorthands/shorthand-parser-errors.js.map +1 -0
  170. package/dist/shorthands/shorthand-parser-utils.d.ts +24 -0
  171. package/dist/shorthands/shorthand-parser-utils.d.ts.map +1 -0
  172. package/dist/shorthands/shorthand-parser-utils.js +398 -0
  173. package/dist/shorthands/shorthand-parser-utils.js.map +1 -0
  174. package/dist/shorthands/shorthand-types.d.ts +64 -0
  175. package/dist/shorthands/shorthand-types.d.ts.map +1 -0
  176. package/dist/shorthands/shorthand-types.js +2 -0
  177. package/dist/shorthands/shorthand-types.js.map +1 -0
  178. package/dist/shorthands/shorthands-ast-evaluation.d.ts +5 -0
  179. package/dist/shorthands/shorthands-ast-evaluation.d.ts.map +1 -0
  180. package/dist/shorthands/shorthands-ast-evaluation.js +19 -0
  181. package/dist/shorthands/shorthands-ast-evaluation.js.map +1 -0
  182. package/dist/tokenizers/css-value-tokenizer.d.ts +43 -0
  183. package/dist/tokenizers/css-value-tokenizer.d.ts.map +1 -0
  184. package/dist/tokenizers/css-value-tokenizer.js +154 -0
  185. package/dist/tokenizers/css-value-tokenizer.js.map +1 -0
  186. package/dist/tokenizers/index.d.ts +2 -0
  187. package/dist/tokenizers/index.d.ts.map +1 -0
  188. package/dist/tokenizers/index.js +2 -0
  189. package/dist/tokenizers/index.js.map +1 -0
  190. package/package.json +54 -0
  191. package/src/compounds/compound-css-data.ts +24 -0
  192. package/src/compounds/compound-mapper.ts +21 -0
  193. package/src/compounds/compound-parser-utils.ts +47 -0
  194. package/src/compounds/compound-types.ts +35 -0
  195. package/src/compounds/compound-value-parsers.ts +12 -0
  196. package/src/compounds/index.ts +5 -0
  197. package/src/compounds/parsers/index.ts +1 -0
  198. package/src/compounds/parsers/shadow-compound.ts +56 -0
  199. package/src/css-data-types/data-types-consts.ts +877 -0
  200. package/src/css-data-types/data-types-predicates.ts +477 -0
  201. package/src/css-data-types/data-types-state-machines.ts +169 -0
  202. package/src/css-data-types/data-types-types.ts +43 -0
  203. package/src/css-data-types/data-types-utils.ts +258 -0
  204. package/src/css-data-types/data-types.ts +435 -0
  205. package/src/css-data-types/index.ts +6 -0
  206. package/src/index.ts +4 -0
  207. package/src/shorthands/index.ts +7 -0
  208. package/src/shorthands/openers/background-position-shorthand.ts +180 -0
  209. package/src/shorthands/openers/background-shorthand.ts +161 -0
  210. package/src/shorthands/openers/border-image-shorthand.ts +35 -0
  211. package/src/shorthands/openers/border-radius-shorthand.ts +93 -0
  212. package/src/shorthands/openers/border-shorthand.ts +198 -0
  213. package/src/shorthands/openers/flex-flow-shorthand.ts +24 -0
  214. package/src/shorthands/openers/flex-shorthand.ts +79 -0
  215. package/src/shorthands/openers/font-shorthand.ts +85 -0
  216. package/src/shorthands/openers/gap-shorthand.ts +47 -0
  217. package/src/shorthands/openers/grid-axis-shorthand.ts +61 -0
  218. package/src/shorthands/openers/grid-gap-shorthand.ts +40 -0
  219. package/src/shorthands/openers/grid-shorthand.ts +260 -0
  220. package/src/shorthands/openers/grid-template-shorthand.ts +176 -0
  221. package/src/shorthands/openers/index.ts +21 -0
  222. package/src/shorthands/openers/list-style-shorthand.ts +33 -0
  223. package/src/shorthands/openers/margin-shorthand.ts +20 -0
  224. package/src/shorthands/openers/outline-shorthand.ts +27 -0
  225. package/src/shorthands/openers/overflow-shorthand.ts +40 -0
  226. package/src/shorthands/openers/padding-shorthand.ts +21 -0
  227. package/src/shorthands/openers/place-content-shorthand.ts +49 -0
  228. package/src/shorthands/openers/place-items-shorthand.ts +43 -0
  229. package/src/shorthands/openers/text-decoration-shorthand.ts +27 -0
  230. package/src/shorthands/shorthand-css-data.ts +210 -0
  231. package/src/shorthands/shorthand-mapper.ts +157 -0
  232. package/src/shorthands/shorthand-parser-errors.ts +47 -0
  233. package/src/shorthands/shorthand-parser-utils.ts +602 -0
  234. package/src/shorthands/shorthand-types.ts +107 -0
  235. package/src/shorthands/shorthands-ast-evaluation.ts +38 -0
  236. package/src/tokenizers/css-value-tokenizer.ts +220 -0
  237. package/src/tokenizers/index.ts +1 -0
@@ -0,0 +1,7 @@
1
+ export * from './shorthand-css-data.js';
2
+ export * from './shorthand-types.js';
3
+ export * from './shorthand-parser-errors.js';
4
+ export * from './shorthands-ast-evaluation.js';
5
+ export * from './shorthand-parser-utils.js';
6
+ export * from './shorthand-mapper.js';
7
+ export * from './openers/index.js';
@@ -0,0 +1,180 @@
1
+ import type { EvaluatedAst, ShorthandCloser, ShorthandOpener } from '../shorthand-types.js';
2
+ import {
3
+ BG_POSITION_CENTER_KEYWORD,
4
+ BG_POSITION_HORIZONTAL_KEYWORDS_MAP,
5
+ BG_POSITION_VERTICAL_KEYWORDS_MAP,
6
+ lengthPercentageDataType,
7
+ universalDataType,
8
+ unorderedListPredicate,
9
+ } from '../../css-data-types/index.js';
10
+ import { createCssValueAST } from '../../tokenizers/index.js';
11
+ import { NoDataTypeMatchError } from '../shorthand-parser-errors.js';
12
+ import { evaluateAst } from '../shorthands-ast-evaluation.js';
13
+ import type { BackgroundPositionLonghand, OpenedBackgroundPositionShorthand } from '../shorthand-css-data.js';
14
+ import { createShorthandCloser, shorthandCloserTemplate } from '../shorthand-parser-utils.js';
15
+
16
+ const centerKeyword = unorderedListPredicate(BG_POSITION_CENTER_KEYWORD);
17
+ const xKeyword = unorderedListPredicate(BG_POSITION_HORIZONTAL_KEYWORDS_MAP);
18
+ const yKeyword = unorderedListPredicate(BG_POSITION_VERTICAL_KEYWORDS_MAP);
19
+ const lengthPercentageValue = lengthPercentageDataType.predicate;
20
+ const universalValue = universalDataType.predicate;
21
+
22
+ function backgroundPositionOpener<V>(nodes: EvaluatedAst<V>[]): OpenedBackgroundPositionShorthand<V> {
23
+ if (nodes.some((node) => node.value.type === ',')) {
24
+ throw new Error('background-position value with a single layer should be provided.');
25
+ }
26
+
27
+ // 1-value syntax
28
+ if (nodes.length === 1) {
29
+ const node = nodes[0]!;
30
+ if (centerKeyword(node.value) || universalValue(node.value)) {
31
+ return {
32
+ 'background-position-x': [node],
33
+ 'background-position-y': [node],
34
+ };
35
+ } else if (xKeyword(node.value) || lengthPercentageValue(node.value)) {
36
+ return {
37
+ 'background-position-x': [node],
38
+ 'background-position-y': [{ value: createCssValueAST('center')[0]!, isImplicit: true }],
39
+ };
40
+ } else if (yKeyword(node.value)) {
41
+ return {
42
+ 'background-position-x': [{ value: createCssValueAST('center')[0]!, isImplicit: true }],
43
+ 'background-position-y': [node],
44
+ };
45
+ } else {
46
+ throw new NoDataTypeMatchError(node.value.text);
47
+ }
48
+ }
49
+
50
+ // 2-value syntax
51
+ if (nodes.length === 2) {
52
+ const [node1, node2] = nodes as [EvaluatedAst<V>, EvaluatedAst<V>];
53
+ if (centerKeyword(node1.value)) {
54
+ if (centerKeyword(node2.value) || yKeyword(node2.value) || lengthPercentageValue(node2.value)) {
55
+ return {
56
+ 'background-position-x': [node1],
57
+ 'background-position-y': [node2],
58
+ };
59
+ } else if (xKeyword(node2.value)) {
60
+ return {
61
+ 'background-position-x': [node2],
62
+ 'background-position-y': [node1],
63
+ };
64
+ } else {
65
+ throw new NoDataTypeMatchError(node2.value.text);
66
+ }
67
+ } else if (xKeyword(node1.value) || lengthPercentageValue(node1.value)) {
68
+ if (centerKeyword(node2.value) || yKeyword(node2.value) || lengthPercentageValue(node2.value)) {
69
+ return {
70
+ 'background-position-x': [node1],
71
+ 'background-position-y': [node2],
72
+ };
73
+ } else {
74
+ throw new NoDataTypeMatchError(node2.value.text);
75
+ }
76
+ } else if (yKeyword(node1.value)) {
77
+ if (centerKeyword(node2.value) || xKeyword(node2.value) || lengthPercentageValue(node2.value)) {
78
+ return {
79
+ 'background-position-x': [node2],
80
+ 'background-position-y': [node1],
81
+ };
82
+ } else {
83
+ throw new NoDataTypeMatchError(node2.value.text);
84
+ }
85
+ } else {
86
+ throw new NoDataTypeMatchError(node1.value.text);
87
+ }
88
+ }
89
+
90
+ // 3-value syntax
91
+ if (nodes.length === 3) {
92
+ const [node1, node2, node3] = nodes as [EvaluatedAst<V>, EvaluatedAst<V>, EvaluatedAst<V>];
93
+ if (centerKeyword(node1.value)) {
94
+ if (xKeyword(node2.value) && lengthPercentageValue(node3.value)) {
95
+ return {
96
+ 'background-position-x': [node2, node3],
97
+ 'background-position-y': [node1],
98
+ };
99
+ } else if (yKeyword(node2.value) && lengthPercentageValue(node3.value)) {
100
+ return {
101
+ 'background-position-x': [node1],
102
+ 'background-position-y': [node2, node3],
103
+ };
104
+ } else {
105
+ throw new Error('Invalid data types of the second and third values.');
106
+ }
107
+ } else if (xKeyword(node1.value)) {
108
+ if (yKeyword(node2.value) && lengthPercentageValue(node3.value)) {
109
+ return {
110
+ 'background-position-x': [node1],
111
+ 'background-position-y': [node2, node3],
112
+ };
113
+ } else if (lengthPercentageValue(node2.value) && (yKeyword(node3.value) || centerKeyword(node3.value))) {
114
+ return {
115
+ 'background-position-x': [node1, node2],
116
+ 'background-position-y': [node3],
117
+ };
118
+ } else {
119
+ throw new Error('Invalid data types of the second and third values.');
120
+ }
121
+ } else if (yKeyword(node1.value)) {
122
+ if (xKeyword(node2.value) && lengthPercentageValue(node3.value)) {
123
+ return {
124
+ 'background-position-x': [node2, node3],
125
+ 'background-position-y': [node1],
126
+ };
127
+ } else if (lengthPercentageValue(node2.value) && (xKeyword(node3.value) || centerKeyword(node3.value))) {
128
+ return {
129
+ 'background-position-x': [node3],
130
+ 'background-position-y': [node1, node2],
131
+ };
132
+ } else {
133
+ throw new Error('Invalid data types of the second and third values.');
134
+ }
135
+ } else {
136
+ throw new NoDataTypeMatchError(node1.value.text);
137
+ }
138
+ }
139
+
140
+ // 4-value syntax
141
+ if (nodes.length === 4) {
142
+ const [node1, node2, node3, node4] = nodes as [
143
+ EvaluatedAst<V>,
144
+ EvaluatedAst<V>,
145
+ EvaluatedAst<V>,
146
+ EvaluatedAst<V>,
147
+ ];
148
+ if (!lengthPercentageValue(node2.value) || !lengthPercentageValue(node4.value)) {
149
+ throw new Error('The second and fourth values are not <length-percentage>.');
150
+ }
151
+ if (xKeyword(node1.value) && yKeyword(node3.value)) {
152
+ return {
153
+ 'background-position-x': [node1, node2],
154
+ 'background-position-y': [node3, node4],
155
+ };
156
+ } else if (yKeyword(node1.value) && xKeyword(node3.value)) {
157
+ return {
158
+ 'background-position-x': [node3, node4],
159
+ 'background-position-y': [node1, node2],
160
+ };
161
+ } else {
162
+ throw new Error('Invalid data types of the first and third values.');
163
+ }
164
+ }
165
+
166
+ throw new Error('Invalid shorthand syntax: 0 or more than 4 values.');
167
+ }
168
+
169
+ export const openBackgroundPositionShorthand =
170
+ <V>(): ShorthandOpener<V, BackgroundPositionLonghand, OpenedBackgroundPositionShorthand<V>> =>
171
+ (shortHand, api) => {
172
+ const astNodes = evaluateAst(shortHand, api);
173
+ return backgroundPositionOpener(astNodes);
174
+ };
175
+
176
+ export const closeBackgroundPositionShorthand = <V>(): ShorthandCloser<
177
+ V,
178
+ BackgroundPositionLonghand,
179
+ OpenedBackgroundPositionShorthand<V>
180
+ > => createShorthandCloser(shorthandCloserTemplate`${'background-position-x'} ${'background-position-y'}`);
@@ -0,0 +1,161 @@
1
+ import type { Backgrounds, BackgroundLayer, OpenedBackgroundShorthand } from '../shorthand-css-data.js';
2
+ import type {
3
+ CSSAstNode,
4
+ EvaluatedAst,
5
+ OpenedShorthand,
6
+ ShorthandOpener,
7
+ ShorthandPart,
8
+ ShorthandCloser,
9
+ OpenedShorthandValue,
10
+ } from '../shorthand-types.js';
11
+
12
+ import {
13
+ imageSourceDataType,
14
+ bgPositionDataType,
15
+ bgSizeDataType,
16
+ repeatStyleDataType,
17
+ attachmentDataType,
18
+ backgroundOriginDataType,
19
+ backgroundClipDataType,
20
+ backgroundColorDataType,
21
+ } from '../../css-data-types/index.js';
22
+ import { valueTextNode } from '../../tokenizers/index.js';
23
+ import {
24
+ splitSimpleShorthandOpener,
25
+ unorderedListShorthandOpener,
26
+ getOpenedLayer,
27
+ layersShorthandOpener,
28
+ createShorthandOpener,
29
+ getOpenedNode,
30
+ shorthandCloserTemplate,
31
+ fixAstNodesPositions,
32
+ } from '../shorthand-parser-utils.js';
33
+
34
+ // background
35
+ export const openBackgroundShorthand = <V>(): ShorthandOpener<V, Backgrounds, OpenedBackgroundShorthand<V>> => {
36
+ const bgLayerShorthandParts: ShorthandPart<V>[] = [
37
+ { prop: 'background-image', dataType: imageSourceDataType },
38
+ { prop: 'background-position', dataType: bgPositionDataType, multipleItems: true },
39
+ { prop: 'background-size', dataType: bgSizeDataType, multipleItems: true },
40
+ { prop: 'background-repeat', dataType: repeatStyleDataType, multipleItems: true },
41
+ { prop: 'background-attachment', dataType: attachmentDataType },
42
+ {
43
+ prop: 'background-origin',
44
+ dataType: backgroundOriginDataType,
45
+ partOpener: splitSimpleShorthandOpener(['background-origin', 'background-clip']),
46
+ },
47
+ { prop: 'background-clip', dataType: backgroundClipDataType },
48
+ ];
49
+ const lastBgLayerShorthandParts: ShorthandPart<V>[] = [
50
+ {
51
+ prop: 'background-color',
52
+ dataType: backgroundColorDataType,
53
+ },
54
+ ].concat(bgLayerShorthandParts);
55
+ const openBackgroundShorthandLayerInner = unorderedListShorthandOpener<V, Backgrounds>(bgLayerShorthandParts);
56
+ const openBackgroundShorthandLastLayerInner = unorderedListShorthandOpener<V, Backgrounds>(
57
+ lastBgLayerShorthandParts,
58
+ );
59
+
60
+ const backgroundShorthandOpener = createShorthandOpener({
61
+ prop: 'background',
62
+ parts: lastBgLayerShorthandParts as ShorthandPart<V, Backgrounds>[],
63
+ shorthandOpener: (astNodes, api) =>
64
+ layersShorthandOpener(
65
+ 'background',
66
+ openBackgroundShorthandLayerInner,
67
+ bgLayerShorthandParts,
68
+ openBackgroundShorthandLastLayerInner,
69
+ lastBgLayerShorthandParts,
70
+ )(astNodes, api),
71
+ });
72
+
73
+ const multipleItemProps = bgLayerShorthandParts
74
+ .filter((part) => part.multipleItems)
75
+ .map((part) => part.prop as Backgrounds);
76
+
77
+ return (shortHand, api) => {
78
+ const openedShorthand = backgroundShorthandOpener(shortHand, api);
79
+
80
+ const layers: OpenedShorthand<V>[] = [];
81
+ let currLayer: OpenedShorthand<V> | undefined;
82
+ for (let i = 0; (currLayer = getOpenedLayer(openedShorthand, i, multipleItemProps)) !== undefined; i++) {
83
+ layers.push(currLayer);
84
+ }
85
+
86
+ const color = layers[0]!['background-color'] as EvaluatedAst<V>;
87
+ for (const layer of layers) {
88
+ delete layer['background-color'];
89
+ }
90
+
91
+ return {
92
+ layers: layers as BackgroundLayer<V>[],
93
+ color,
94
+ };
95
+ };
96
+ };
97
+
98
+ export const closeBackgroundShorthand =
99
+ <V>(): ShorthandCloser<V, Backgrounds, OpenedBackgroundShorthand<V>> =>
100
+ (opened, api, detachExpression) => {
101
+ const layerTemplate = shorthandCloserTemplate<
102
+ keyof BackgroundLayer<V>
103
+ >`${'background-image'} ${'background-position'} / ${'background-size'} ${'background-repeat'} ${'background-attachment'} ${'background-origin'} ${'background-clip'}`;
104
+
105
+ const backgroundLayerCloser: ShorthandCloser<V, keyof BackgroundLayer<V>, BackgroundLayer<V>> = (
106
+ opened,
107
+ api,
108
+ detachExpressions = false,
109
+ ) => {
110
+ const multiExpressions: string[] = [];
111
+
112
+ // Background shorthand syntax allows an arbitrary order of sub-properties. So, in most
113
+ // cases, it's safe to omit implicit values. One exception is background-position: it
114
+ // cannot be skipped if there is an explicitly specified background-size. Also, we can
115
+ // omit unnecessary duplicates: when background-origin and background-clip are equal,
116
+ // we can omit background-clip and keep a single value for both.
117
+ function isSafeToOmit<V>(propName: string, value: OpenedShorthandValue<V>): boolean {
118
+ if (propName === 'background-position' && opened['background-size'].some((n) => !n.isImplicit)) {
119
+ return false;
120
+ }
121
+
122
+ const isImplicit = Array.isArray(value) ? value.every((n) => n.isImplicit) : value.isImplicit;
123
+
124
+ const unnecessaryBackgroundClip =
125
+ propName === 'background-clip' &&
126
+ opened['background-clip'].value.text === opened['background-origin'].value.text;
127
+
128
+ return isImplicit || unnecessaryBackgroundClip;
129
+ }
130
+
131
+ return fixAstNodesPositions(
132
+ (layerTemplate.strings as string[]).reduce((nodes, currString, index) => {
133
+ const currKey = layerTemplate.keys[index];
134
+
135
+ if (currKey === undefined || isSafeToOmit(currKey, opened[currKey])) {
136
+ return nodes;
137
+ }
138
+
139
+ return nodes.concat(
140
+ valueTextNode(currString),
141
+ getOpenedNode(opened[currKey], api, detachExpressions, multiExpressions),
142
+ );
143
+ }, [] as CSSAstNode<V>[]),
144
+ api,
145
+ );
146
+ };
147
+
148
+ let nonColorLayers: CSSAstNode<V>[] = [];
149
+ opened.layers.forEach((layer) => {
150
+ nonColorLayers = nonColorLayers.concat(backgroundLayerCloser(layer, api, detachExpression));
151
+ nonColorLayers.push({ ...valueTextNode(','), type: ',' });
152
+ });
153
+ nonColorLayers.pop();
154
+
155
+ return fixAstNodesPositions(
156
+ opened.color.isImplicit
157
+ ? nonColorLayers
158
+ : nonColorLayers.concat(getOpenedNode(opened.color, api, detachExpression)),
159
+ api,
160
+ );
161
+ };
@@ -0,0 +1,35 @@
1
+ import type { BorderImages, OpenedBorderImageShorthand } from '../shorthand-css-data.js';
2
+ import type { ShorthandOpener, GetShorthandCloser } from '../shorthand-types.js';
3
+
4
+ import {
5
+ imageSourceDataType,
6
+ borderImageSliceDataType,
7
+ borderImageWidthDataType,
8
+ borderImageOutsetDataType,
9
+ borderImageRepeatDataType,
10
+ } from '../../css-data-types/index.js';
11
+ import {
12
+ unorderedListShorthandOpener,
13
+ createShorthandOpener,
14
+ shorthandCloserTemplate,
15
+ createShorthandCloser,
16
+ } from '../shorthand-parser-utils.js';
17
+
18
+ // border-image
19
+ export const openBorderImageShorthand = <V>(): ShorthandOpener<V, BorderImages, OpenedBorderImageShorthand<V>> =>
20
+ createShorthandOpener({
21
+ prop: 'border-image',
22
+ parts: [
23
+ { prop: 'border-image-source', dataType: imageSourceDataType },
24
+ { prop: 'border-image-slice', dataType: borderImageSliceDataType, multipleItems: true },
25
+ { prop: 'border-image-width', dataType: borderImageWidthDataType, multipleItems: true },
26
+ { prop: 'border-image-outset', dataType: borderImageOutsetDataType, multipleItems: true },
27
+ { prop: 'border-image-repeat', dataType: borderImageRepeatDataType, multipleItems: true },
28
+ ],
29
+ shorthandOpener: (astNodes, api, parts) => unorderedListShorthandOpener(parts)(astNodes, api),
30
+ }) as ShorthandOpener<V, BorderImages, OpenedBorderImageShorthand<V>>;
31
+
32
+ export const closeBorderImageShorthand: GetShorthandCloser<BorderImages> = <V>() =>
33
+ createShorthandCloser<V, BorderImages>(
34
+ shorthandCloserTemplate<BorderImages>`${'border-image-source'} ${'border-image-slice'} / ${'border-image-width'} / ${'border-image-outset'} ${'border-image-repeat'}`,
35
+ );
@@ -0,0 +1,93 @@
1
+ import type { BorderRadiuses, OpenedBorderRadiusShorthand } from '../shorthand-css-data.js';
2
+ import type {
3
+ CSSAstNode,
4
+ OpenedShorthand,
5
+ SimpleOpenedShorthand,
6
+ ShorthandOpener,
7
+ ShorthandCloser,
8
+ } from '../shorthand-types.js';
9
+
10
+ import { ALWAYS_DATA_TYPE, INTERNAL_VALUE_SEPERATOR } from '../../css-data-types/index.js';
11
+ import { valueTextNode } from '../../tokenizers/index.js';
12
+ import {
13
+ edgesShorthandOpener,
14
+ getShorthandLayers,
15
+ getOpenedLayer,
16
+ createShorthandOpener,
17
+ edgesShorthandCloser,
18
+ fixAstNodesPositions,
19
+ } from '../shorthand-parser-utils.js';
20
+
21
+ // border-radius
22
+ export const openBorderRadiusShorthand = <V>(): ShorthandOpener<V, BorderRadiuses, OpenedBorderRadiusShorthand<V>> => {
23
+ const singleBorderRadiusShorthandOpenerInner = edgesShorthandOpener<V, BorderRadiuses>('border-radius', true);
24
+
25
+ const borderRadiusShorthandOpener = createShorthandOpener<V, BorderRadiuses>({
26
+ prop: 'border-radius',
27
+ parts: [
28
+ {
29
+ prop: 'border-radius',
30
+ dataType: ALWAYS_DATA_TYPE,
31
+ openedProps: [
32
+ 'border-top-left-radius',
33
+ 'border-top-right-radius',
34
+ 'border-bottom-right-radius',
35
+ 'border-bottom-left-radius',
36
+ ],
37
+ },
38
+ ],
39
+ shorthandOpener: (astNodes, api) => {
40
+ const [firstLayer, secondLayer] = getShorthandLayers(astNodes, INTERNAL_VALUE_SEPERATOR);
41
+ const firstOpened = singleBorderRadiusShorthandOpenerInner(firstLayer!, api);
42
+ const secondOpened =
43
+ secondLayer && secondLayer.length > 0
44
+ ? singleBorderRadiusShorthandOpenerInner(secondLayer, api)
45
+ : undefined;
46
+
47
+ const opened: OpenedShorthand<V> = {};
48
+ const props = Object.keys(firstOpened) as BorderRadiuses[];
49
+ for (const prop of props) {
50
+ opened[prop] = [firstOpened[prop]];
51
+ if (secondOpened) {
52
+ opened[prop].push(secondOpened[prop]);
53
+ }
54
+ }
55
+ return opened;
56
+ },
57
+ });
58
+
59
+ return (shortHand, api) => {
60
+ const openedShorthand = borderRadiusShorthandOpener(shortHand, api);
61
+
62
+ const layers: SimpleOpenedShorthand<V, BorderRadiuses>[] = [];
63
+ let currLayer: SimpleOpenedShorthand<V, BorderRadiuses> | undefined;
64
+ for (
65
+ let i = 0;
66
+ (currLayer = getOpenedLayer(openedShorthand, i) as SimpleOpenedShorthand<V, BorderRadiuses> | undefined) !==
67
+ undefined;
68
+ i++
69
+ ) {
70
+ layers.push(currLayer);
71
+ }
72
+
73
+ return layers;
74
+ };
75
+ };
76
+
77
+ export const closeBorderRadiusShorthand =
78
+ <V>(): ShorthandCloser<V, BorderRadiuses, SimpleOpenedShorthand<V, BorderRadiuses>[]> =>
79
+ (opened, api, detachExpression) => {
80
+ if (!opened[0]) {
81
+ return [];
82
+ }
83
+ const borderRadiusLayerCloser = edgesShorthandCloser<V, BorderRadiuses>('border-radius', true);
84
+ let closedLayers: CSSAstNode<V>[] = [];
85
+ closedLayers = closedLayers.concat(borderRadiusLayerCloser(opened[0], api, detachExpression));
86
+ if (opened[1]) {
87
+ closedLayers = closedLayers.concat(
88
+ valueTextNode(INTERNAL_VALUE_SEPERATOR),
89
+ borderRadiusLayerCloser(opened[1], api, detachExpression),
90
+ );
91
+ }
92
+ return fixAstNodesPositions(closedLayers, api);
93
+ };
@@ -0,0 +1,198 @@
1
+ import type {
2
+ BorderStyles,
3
+ BorderWidths,
4
+ BorderColors,
5
+ BordersShallow,
6
+ Borders,
7
+ BordersTop,
8
+ BordersRight,
9
+ BordersBottom,
10
+ BordersLeft,
11
+ CssEdge,
12
+ } from '../shorthand-css-data.js';
13
+ import type {
14
+ SimpleOpenedShorthand,
15
+ SimpleShorthandOpener,
16
+ ShorthandPart,
17
+ GetSimpleShorthandOpener,
18
+ ShorthandCloser,
19
+ GetShorthandCloser,
20
+ } from '../shorthand-types.js';
21
+
22
+ import { type DataType, lineStyleDataType, lineWidthDataType, colorDataType } from '../../css-data-types/index.js';
23
+ import {
24
+ edgesShorthandOpener,
25
+ unorderedListShorthandOpener,
26
+ createShorthandOpener,
27
+ createShorthandOpenerFromPart,
28
+ getOpenedNodeValue,
29
+ edgesShorthandCloser,
30
+ shorthandCloserTemplate,
31
+ createShorthandCloser,
32
+ } from '../shorthand-parser-utils.js';
33
+ import { CannotCloseBorderError } from '../shorthand-parser-errors.js';
34
+
35
+ const borderShorthandPart = <V, T extends string>(
36
+ prop: string,
37
+ dataType: DataType,
38
+ openedProps?: T[],
39
+ ): ShorthandPart<V, T> => ({
40
+ prop,
41
+ dataType,
42
+ partOpener: openedProps ? edgesShorthandOpener(prop) : undefined,
43
+ openedProps,
44
+ });
45
+
46
+ const getBorderStyleShorthandPart = <V>() =>
47
+ borderShorthandPart<V, BorderStyles>('border-style', lineStyleDataType, [
48
+ 'border-top-style',
49
+ 'border-right-style',
50
+ 'border-bottom-style',
51
+ 'border-left-style',
52
+ ]);
53
+ const getBorderWidthShorthandPart = <V>() =>
54
+ borderShorthandPart<V, BorderWidths>('border-width', lineWidthDataType, [
55
+ 'border-top-width',
56
+ 'border-right-width',
57
+ 'border-bottom-width',
58
+ 'border-left-width',
59
+ ]);
60
+
61
+ const getBorderColorShorthandPart = <V>() =>
62
+ borderShorthandPart<V, BorderColors>('border-color', colorDataType, [
63
+ 'border-top-color',
64
+ 'border-right-color',
65
+ 'border-bottom-color',
66
+ 'border-left-color',
67
+ ]);
68
+
69
+ // border
70
+ export const openBorderShorthand: GetSimpleShorthandOpener<Borders> = <V>() =>
71
+ createShorthandOpener({
72
+ prop: 'border',
73
+ parts: [
74
+ getBorderStyleShorthandPart(),
75
+ getBorderWidthShorthandPart(),
76
+ getBorderColorShorthandPart(),
77
+ ] as ShorthandPart<V, Borders>[],
78
+ shorthandOpener: (astNodes, api, parts, shallow) =>
79
+ unorderedListShorthandOpener(parts, { shallow })(astNodes, api),
80
+ }) as SimpleShorthandOpener<V, Borders>;
81
+
82
+ export const openBorderShorthandShallow: GetSimpleShorthandOpener<BordersShallow> = <V>() => {
83
+ const borderShallowOpener: SimpleShorthandOpener<V, BordersShallow> = (shortHand, api) =>
84
+ openBorderShorthand<V>()(shortHand, api, true) as unknown as SimpleOpenedShorthand<V, BordersShallow>;
85
+ return borderShallowOpener;
86
+ };
87
+
88
+ export const closeBorderShorthand =
89
+ <V>(): ShorthandCloser<V, Borders> =>
90
+ (opened, api, detachExpression, shallow) => {
91
+ if (shallow) {
92
+ const borderShallowCloser = createShorthandCloser<V, BordersShallow>(
93
+ shorthandCloserTemplate<BordersShallow>`${'border-style'} ${'border-width'} ${'border-color'}`,
94
+ );
95
+ return borderShallowCloser(
96
+ opened as unknown as SimpleOpenedShorthand<V, BordersShallow>,
97
+ api,
98
+ detachExpression,
99
+ );
100
+ }
101
+
102
+ const borderClosedTop = closeBorderTopShorthand<V>()(opened, api, detachExpression);
103
+ const borderClosedTopValue = getOpenedNodeValue(borderClosedTop, api);
104
+ if (
105
+ getOpenedNodeValue(closeBorderRightShorthand<V>()(opened, api, detachExpression), api) !==
106
+ borderClosedTopValue ||
107
+ getOpenedNodeValue(closeBorderBottomShorthand<V>()(opened, api, detachExpression), api) !==
108
+ borderClosedTopValue ||
109
+ getOpenedNodeValue(closeBorderLeftShorthand<V>()(opened, api, detachExpression), api) !==
110
+ borderClosedTopValue
111
+ ) {
112
+ throw new CannotCloseBorderError();
113
+ }
114
+
115
+ return borderClosedTop;
116
+ };
117
+
118
+ const borderEdgeProp = (edge: CssEdge, item: string) => `border-${edge}-${item}`;
119
+ const borderEdgeShorthandOpener = <V, T extends string>(edge: CssEdge) =>
120
+ createShorthandOpener({
121
+ prop: `border-${edge}`,
122
+ parts: [
123
+ borderShorthandPart<V, BorderStyles>(borderEdgeProp(edge, 'style'), lineStyleDataType),
124
+ borderShorthandPart<V, BorderWidths>(borderEdgeProp(edge, 'width'), lineWidthDataType),
125
+ borderShorthandPart<V, BorderColors>(borderEdgeProp(edge, 'color'), colorDataType),
126
+ ] as ShorthandPart<V, T>[],
127
+ shorthandOpener: (astNodes, api, parts) =>
128
+ unorderedListShorthandOpener(parts, { shallow: true })(astNodes, api),
129
+ }) as SimpleShorthandOpener<V, T>;
130
+
131
+ // border-top
132
+ export const openBorderTopShorthand: GetSimpleShorthandOpener<BordersTop> = <V>() =>
133
+ borderEdgeShorthandOpener<V, BordersTop>('top');
134
+
135
+ export const closeBorderTopShorthand: GetShorthandCloser<BordersTop> = <V>() =>
136
+ createShorthandCloser<V, BordersTop>(
137
+ shorthandCloserTemplate<BordersTop>`${borderEdgeProp('top', 'style')} ${borderEdgeProp(
138
+ 'top',
139
+ 'width',
140
+ )} ${borderEdgeProp('top', 'color')}`,
141
+ );
142
+
143
+ // border-right
144
+ export const openBorderRightShorthand: GetSimpleShorthandOpener<BordersRight> = <V>() =>
145
+ borderEdgeShorthandOpener<V, BordersRight>('right');
146
+
147
+ export const closeBorderRightShorthand: GetShorthandCloser<BordersRight> = <V>() =>
148
+ createShorthandCloser<V, BordersRight>(
149
+ shorthandCloserTemplate<BordersRight>`${borderEdgeProp('right', 'style')} ${borderEdgeProp(
150
+ 'right',
151
+ 'width',
152
+ )} ${borderEdgeProp('right', 'color')}`,
153
+ );
154
+
155
+ // border-bottom
156
+ export const openBorderBottomShorthand: GetSimpleShorthandOpener<BordersBottom> = <V>() =>
157
+ borderEdgeShorthandOpener<V, BordersBottom>('bottom');
158
+
159
+ export const closeBorderBottomShorthand: GetShorthandCloser<BordersBottom> = <V>() =>
160
+ createShorthandCloser<V, BordersBottom>(
161
+ shorthandCloserTemplate<BordersBottom>`${borderEdgeProp('bottom', 'style')} ${borderEdgeProp(
162
+ 'bottom',
163
+ 'width',
164
+ )} ${borderEdgeProp('bottom', 'color')}`,
165
+ );
166
+
167
+ // border-left
168
+ export const openBorderLeftShorthand: GetSimpleShorthandOpener<BordersLeft> = <V>() =>
169
+ borderEdgeShorthandOpener<V, BordersLeft>('left');
170
+
171
+ export const closeBorderLeftShorthand: GetShorthandCloser<BordersLeft> = <V>() =>
172
+ createShorthandCloser<V, BordersLeft>(
173
+ shorthandCloserTemplate<BordersLeft>`${borderEdgeProp('left', 'style')} ${borderEdgeProp(
174
+ 'left',
175
+ 'width',
176
+ )} ${borderEdgeProp('left', 'color')}`,
177
+ );
178
+
179
+ // border-style
180
+ export const openBorderStyleShorthand: GetSimpleShorthandOpener<BorderStyles> = <V>() =>
181
+ createShorthandOpenerFromPart(getBorderStyleShorthandPart<V>());
182
+
183
+ export const closeBorderStyleShorthand: GetShorthandCloser<BorderStyles> = <V>() =>
184
+ edgesShorthandCloser<V, BorderStyles>('border-style');
185
+
186
+ // border-width
187
+ export const openBorderWidthShorthand: GetSimpleShorthandOpener<BorderWidths> = <V>() =>
188
+ createShorthandOpenerFromPart(getBorderWidthShorthandPart<V>());
189
+
190
+ export const closeBorderWidthShorthand: GetShorthandCloser<BorderWidths> = <V>() =>
191
+ edgesShorthandCloser<V, BorderWidths>('border-width');
192
+
193
+ // border-color
194
+ export const openBorderColorShorthand: GetSimpleShorthandOpener<BorderColors> = <V>() =>
195
+ createShorthandOpenerFromPart(getBorderColorShorthandPart<V>());
196
+
197
+ export const closeBorderColorShorthand: GetShorthandCloser<BorderColors> = <V>() =>
198
+ edgesShorthandCloser<V, BorderColors>('border-color');