@jesscss/core 2.0.0-alpha.5 → 2.0.0-alpha.6

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 (637) hide show
  1. package/lib/index.cjs +20159 -0
  2. package/lib/index.d.cts +5993 -0
  3. package/lib/index.d.cts.map +1 -0
  4. package/lib/index.d.ts +5992 -21
  5. package/lib/index.d.ts.map +1 -1
  6. package/lib/index.js +19926 -22
  7. package/lib/index.js.map +1 -1
  8. package/package.json +15 -14
  9. package/src/__tests__/define-function-record.test.ts +58 -0
  10. package/src/__tests__/define-function-simple.test.ts +55 -0
  11. package/src/__tests__/define-function-split-sequence.test.ts +547 -0
  12. package/src/__tests__/define-function-type-parity.test.ts +9 -0
  13. package/src/__tests__/define-function.test.ts +763 -0
  14. package/src/__tests__/num-operations.test.ts +91 -0
  15. package/src/__tests__/safe-parse.test.ts +374 -0
  16. package/src/context.ts +896 -0
  17. package/src/conversions.ts +282 -0
  18. package/src/debug-log.ts +29 -0
  19. package/src/define-function.ts +1006 -0
  20. package/src/deprecation.ts +67 -0
  21. package/src/globals.d.ts +26 -0
  22. package/src/index.ts +31 -0
  23. package/src/jess-error.ts +773 -0
  24. package/src/logger/deprecation-processing.ts +109 -0
  25. package/src/logger.ts +31 -0
  26. package/src/plugin.ts +292 -0
  27. package/src/tree/LOOKUP_CHAINS.md +35 -0
  28. package/src/tree/README.md +18 -0
  29. package/src/tree/__tests__/__snapshots__/extend-eval-integration.test.ts.snap +1455 -0
  30. package/src/tree/__tests__/ampersand.test.ts +382 -0
  31. package/src/tree/__tests__/at-rule.test.ts +2047 -0
  32. package/src/tree/__tests__/basic-render.test.ts +212 -0
  33. package/src/tree/__tests__/block.test.ts +40 -0
  34. package/src/tree/__tests__/call.test.ts +346 -0
  35. package/src/tree/__tests__/color.test.ts +537 -0
  36. package/src/tree/__tests__/condition.test.ts +186 -0
  37. package/src/tree/__tests__/control.test.ts +564 -0
  38. package/src/tree/__tests__/declaration.test.ts +253 -0
  39. package/src/tree/__tests__/dependency-graph.test.ts +177 -0
  40. package/src/tree/__tests__/detached-rulesets.test.ts +213 -0
  41. package/src/tree/__tests__/dimension.test.ts +236 -0
  42. package/src/tree/__tests__/expression.test.ts +73 -0
  43. package/src/tree/__tests__/ext-node.test.ts +31 -0
  44. package/src/tree/__tests__/extend-eval-integration.test.ts +1033 -0
  45. package/src/tree/__tests__/extend-import-style.test.ts +929 -0
  46. package/src/tree/__tests__/extend-less-fixtures.test.ts +851 -0
  47. package/src/tree/__tests__/extend-list.test.ts +31 -0
  48. package/src/tree/__tests__/extend-roots.test.ts +1045 -0
  49. package/src/tree/__tests__/extend-rules.test.ts +740 -0
  50. package/src/tree/__tests__/func.test.ts +171 -0
  51. package/src/tree/__tests__/import-js.test.ts +33 -0
  52. package/src/tree/__tests__/import-style-test-helpers.ts +56 -0
  53. package/src/tree/__tests__/import-style.test.ts +1967 -0
  54. package/src/tree/__tests__/interpolated-reference.test.ts +44 -0
  55. package/src/tree/__tests__/interpolated.test.ts +41 -0
  56. package/src/tree/__tests__/list.test.ts +177 -0
  57. package/src/tree/__tests__/log.test.ts +83 -0
  58. package/src/tree/__tests__/mixin-recursion.test.ts +639 -0
  59. package/src/tree/__tests__/mixin.test.ts +2171 -0
  60. package/src/tree/__tests__/negative.test.ts +45 -0
  61. package/src/tree/__tests__/nesting-collapse.test.ts +519 -0
  62. package/src/tree/__tests__/node-flags-perf.test.ts +195 -0
  63. package/src/tree/__tests__/node-flags.test.ts +410 -0
  64. package/src/tree/__tests__/node-graph.test.ts +598 -0
  65. package/src/tree/__tests__/node-mutation.test.ts +182 -0
  66. package/src/tree/__tests__/operation.test.ts +18 -0
  67. package/src/tree/__tests__/paren.test.ts +90 -0
  68. package/src/tree/__tests__/preserve-mode-output.test.ts +50 -0
  69. package/src/tree/__tests__/quoted.test.ts +72 -0
  70. package/src/tree/__tests__/range.test.ts +59 -0
  71. package/src/tree/__tests__/reference.test.ts +743 -0
  72. package/src/tree/__tests__/rest.test.ts +29 -0
  73. package/src/tree/__tests__/rules-raw.test.ts +14 -0
  74. package/src/tree/__tests__/rules.test.ts +1271 -0
  75. package/src/tree/__tests__/ruleset.test.ts +597 -0
  76. package/src/tree/__tests__/selector-attr.test.ts +50 -0
  77. package/src/tree/__tests__/selector-basic.test.ts +44 -0
  78. package/src/tree/__tests__/selector-capture.test.ts +22 -0
  79. package/src/tree/__tests__/selector-complex.test.ts +120 -0
  80. package/src/tree/__tests__/selector-compound.test.ts +74 -0
  81. package/src/tree/__tests__/selector-interpolated.test.ts +50 -0
  82. package/src/tree/__tests__/selector-list.test.ts +59 -0
  83. package/src/tree/__tests__/selector-pseudo.test.ts +23 -0
  84. package/src/tree/__tests__/selector.test.ts +182 -0
  85. package/src/tree/__tests__/sequence.test.ts +226 -0
  86. package/src/tree/__tests__/serialize-types.test.ts +529 -0
  87. package/src/tree/__tests__/spaced.test.ts +8 -0
  88. package/src/tree/__tests__/url.test.ts +72 -0
  89. package/src/tree/__tests__/var-declaration.test.ts +90 -0
  90. package/src/tree/ampersand.ts +538 -0
  91. package/src/tree/any.ts +169 -0
  92. package/src/tree/at-rule.ts +760 -0
  93. package/src/tree/block.ts +72 -0
  94. package/src/tree/bool.ts +46 -0
  95. package/src/tree/call.ts +593 -0
  96. package/src/tree/collection.ts +52 -0
  97. package/src/tree/color.ts +629 -0
  98. package/src/tree/combinator.ts +30 -0
  99. package/src/tree/comment.ts +36 -0
  100. package/src/tree/condition.ts +194 -0
  101. package/src/tree/control.ts +452 -0
  102. package/src/tree/declaration-custom.ts +56 -0
  103. package/src/tree/declaration-var.ts +87 -0
  104. package/src/tree/declaration.ts +742 -0
  105. package/src/tree/default-guard.ts +35 -0
  106. package/src/tree/dimension.ts +392 -0
  107. package/src/tree/expression.ts +97 -0
  108. package/src/tree/extend-list.ts +51 -0
  109. package/src/tree/extend.ts +391 -0
  110. package/src/tree/function.ts +254 -0
  111. package/src/tree/import-js.ts +130 -0
  112. package/src/tree/import-style.ts +875 -0
  113. package/{lib/tree/index.js → src/tree/index.ts} +49 -22
  114. package/src/tree/interpolated.ts +346 -0
  115. package/src/tree/js-array.ts +21 -0
  116. package/src/tree/js-expr.ts +50 -0
  117. package/src/tree/js-function.ts +31 -0
  118. package/src/tree/js-object.ts +22 -0
  119. package/src/tree/list.ts +415 -0
  120. package/src/tree/log.ts +89 -0
  121. package/src/tree/mixin.ts +331 -0
  122. package/src/tree/negative.ts +58 -0
  123. package/src/tree/nil.ts +57 -0
  124. package/src/tree/node-base.ts +1716 -0
  125. package/src/tree/node-type.ts +122 -0
  126. package/src/tree/node.ts +118 -0
  127. package/src/tree/number.ts +54 -0
  128. package/src/tree/operation.ts +187 -0
  129. package/src/tree/paren.ts +132 -0
  130. package/src/tree/query-condition.ts +47 -0
  131. package/src/tree/quoted.ts +119 -0
  132. package/src/tree/range.ts +101 -0
  133. package/src/tree/reference.ts +1099 -0
  134. package/src/tree/rest.ts +55 -0
  135. package/src/tree/rules-raw.ts +52 -0
  136. package/src/tree/rules.ts +2896 -0
  137. package/src/tree/ruleset.ts +1217 -0
  138. package/src/tree/selector-attr.ts +172 -0
  139. package/src/tree/selector-basic.ts +75 -0
  140. package/src/tree/selector-capture.ts +85 -0
  141. package/src/tree/selector-complex.ts +189 -0
  142. package/src/tree/selector-compound.ts +205 -0
  143. package/src/tree/selector-interpolated.ts +95 -0
  144. package/src/tree/selector-list.ts +245 -0
  145. package/src/tree/selector-pseudo.ts +173 -0
  146. package/src/tree/selector-simple.ts +10 -0
  147. package/src/tree/selector.ts +152 -0
  148. package/src/tree/sequence.ts +463 -0
  149. package/src/tree/tree.ts +130 -0
  150. package/src/tree/url.ts +95 -0
  151. package/src/tree/util/EXTEND_ARCHITECTURE_ANALYSIS.md +215 -0
  152. package/src/tree/util/EXTEND_AUDIT.md +233 -0
  153. package/src/tree/util/EXTEND_BASELINE.md +64 -0
  154. package/src/tree/util/EXTEND_CALL_GRAPH_ANALYSIS.md +244 -0
  155. package/src/tree/util/EXTEND_DOCS.md +24 -0
  156. package/src/tree/util/EXTEND_FINAL_SUMMARY.md +95 -0
  157. package/src/tree/util/EXTEND_FUNCTION_AUDIT.md +1433 -0
  158. package/src/tree/util/EXTEND_OPTIMIZATION_PLAN.md +114 -0
  159. package/src/tree/util/EXTEND_REFACTORING_SUMMARY.md +152 -0
  160. package/src/tree/util/EXTEND_RULES.md +74 -0
  161. package/src/tree/util/EXTEND_UNUSED_FUNCTIONS.md +127 -0
  162. package/src/tree/util/EXTEND_UNUSED_FUNCTIONS_ANALYSIS.md +227 -0
  163. package/src/tree/util/NODE_COPY_REDUCTION_PLAN.md +12 -0
  164. package/src/tree/util/__tests__/EXTEND_TEST_INDEX.md +59 -0
  165. package/src/tree/util/__tests__/OPTIMIZATION-ANALYSIS.md +130 -0
  166. package/src/tree/util/__tests__/WALK_AND_CONSUME_DESIGN.md +138 -0
  167. package/src/tree/util/__tests__/_archive/2026-02-09__OPTIMIZATION-ANALYSIS.md +9 -0
  168. package/src/tree/util/__tests__/_archive/README.md +4 -0
  169. package/src/tree/util/__tests__/bitset.test.ts +142 -0
  170. package/src/tree/util/__tests__/debug-log.ts +50 -0
  171. package/src/tree/util/__tests__/extend-comment-handling.test.ts +187 -0
  172. package/src/tree/util/__tests__/extend-core-unit.test.ts +941 -0
  173. package/src/tree/util/__tests__/extend-pipeline-bench.test.ts +154 -0
  174. package/src/tree/util/__tests__/extend-pipeline-bench.ts +190 -0
  175. package/src/tree/util/__tests__/fast-reject.test.ts +377 -0
  176. package/src/tree/util/__tests__/is-node.test.ts +63 -0
  177. package/src/tree/util/__tests__/list-like.test.ts +63 -0
  178. package/src/tree/util/__tests__/outputwriter.test.ts +523 -0
  179. package/src/tree/util/__tests__/print.test.ts +183 -0
  180. package/src/tree/util/__tests__/process-extends.test.ts +226 -0
  181. package/src/tree/util/__tests__/process-leading-is.test.ts +205 -0
  182. package/src/tree/util/__tests__/recursion-helper.test.ts +184 -0
  183. package/src/tree/util/__tests__/selector-match-unit.test.ts +1427 -0
  184. package/src/tree/util/__tests__/sourcemap.test.ts +117 -0
  185. package/src/tree/util/ampersand-template.ts +9 -0
  186. package/src/tree/util/bitset.ts +194 -0
  187. package/src/tree/util/calculate.ts +11 -0
  188. package/src/tree/util/cast.ts +89 -0
  189. package/src/tree/util/cloning.ts +8 -0
  190. package/src/tree/util/collections.ts +299 -0
  191. package/src/tree/util/compare.ts +90 -0
  192. package/src/tree/util/cursor.ts +171 -0
  193. package/src/tree/util/extend-core.ts +2139 -0
  194. package/src/tree/util/extend-roots.ts +1108 -0
  195. package/src/tree/util/field-helpers.ts +354 -0
  196. package/src/tree/util/is-node.ts +43 -0
  197. package/src/tree/util/list-like.ts +93 -0
  198. package/src/tree/util/mixin-instance-primitives.ts +2020 -0
  199. package/src/tree/util/print.ts +303 -0
  200. package/src/tree/util/process-leading-is.ts +421 -0
  201. package/src/tree/util/recursion-helper.ts +54 -0
  202. package/src/tree/util/regex.ts +2 -0
  203. package/src/tree/util/registry-utils.ts +1953 -0
  204. package/src/tree/util/ruleset-trace.ts +17 -0
  205. package/src/tree/util/scoped-body-eval.ts +320 -0
  206. package/src/tree/util/selector-match-core.ts +2005 -0
  207. package/src/tree/util/selector-utils.ts +757 -0
  208. package/src/tree/util/serialize-helper.ts +535 -0
  209. package/src/tree/util/serialize-types.ts +318 -0
  210. package/src/tree/util/should-operate.ts +78 -0
  211. package/src/tree/util/sourcemap.ts +37 -0
  212. package/src/types/config.ts +247 -0
  213. package/src/types/index.ts +12 -0
  214. package/{lib/types/modes.d.ts → src/types/modes.ts} +2 -1
  215. package/src/types.d.ts +9 -0
  216. package/src/types.ts +68 -0
  217. package/src/use-webpack-resolver.ts +56 -0
  218. package/src/visitor/__tests__/visitor.test.ts +136 -0
  219. package/src/visitor/index.ts +263 -0
  220. package/{lib/visitor/less-visitor.js → src/visitor/less-visitor.ts} +3 -2
  221. package/lib/context.d.ts +0 -352
  222. package/lib/context.d.ts.map +0 -1
  223. package/lib/context.js +0 -636
  224. package/lib/context.js.map +0 -1
  225. package/lib/conversions.d.ts +0 -73
  226. package/lib/conversions.d.ts.map +0 -1
  227. package/lib/conversions.js +0 -253
  228. package/lib/conversions.js.map +0 -1
  229. package/lib/debug-log.d.ts +0 -2
  230. package/lib/debug-log.d.ts.map +0 -1
  231. package/lib/debug-log.js +0 -27
  232. package/lib/debug-log.js.map +0 -1
  233. package/lib/define-function.d.ts +0 -587
  234. package/lib/define-function.d.ts.map +0 -1
  235. package/lib/define-function.js +0 -726
  236. package/lib/define-function.js.map +0 -1
  237. package/lib/deprecation.d.ts +0 -34
  238. package/lib/deprecation.d.ts.map +0 -1
  239. package/lib/deprecation.js +0 -57
  240. package/lib/deprecation.js.map +0 -1
  241. package/lib/jess-error.d.ts +0 -343
  242. package/lib/jess-error.d.ts.map +0 -1
  243. package/lib/jess-error.js +0 -508
  244. package/lib/jess-error.js.map +0 -1
  245. package/lib/logger/deprecation-processing.d.ts +0 -41
  246. package/lib/logger/deprecation-processing.d.ts.map +0 -1
  247. package/lib/logger/deprecation-processing.js +0 -81
  248. package/lib/logger/deprecation-processing.js.map +0 -1
  249. package/lib/logger.d.ts +0 -10
  250. package/lib/logger.d.ts.map +0 -1
  251. package/lib/logger.js +0 -20
  252. package/lib/logger.js.map +0 -1
  253. package/lib/plugin.d.ts +0 -94
  254. package/lib/plugin.d.ts.map +0 -1
  255. package/lib/plugin.js +0 -174
  256. package/lib/plugin.js.map +0 -1
  257. package/lib/tree/ampersand.d.ts +0 -98
  258. package/lib/tree/ampersand.d.ts.map +0 -1
  259. package/lib/tree/ampersand.js +0 -319
  260. package/lib/tree/ampersand.js.map +0 -1
  261. package/lib/tree/any.d.ts +0 -58
  262. package/lib/tree/any.d.ts.map +0 -1
  263. package/lib/tree/any.js +0 -104
  264. package/lib/tree/any.js.map +0 -1
  265. package/lib/tree/at-rule.d.ts +0 -53
  266. package/lib/tree/at-rule.d.ts.map +0 -1
  267. package/lib/tree/at-rule.js +0 -503
  268. package/lib/tree/at-rule.js.map +0 -1
  269. package/lib/tree/block.d.ts +0 -22
  270. package/lib/tree/block.d.ts.map +0 -1
  271. package/lib/tree/block.js +0 -24
  272. package/lib/tree/block.js.map +0 -1
  273. package/lib/tree/bool.d.ts +0 -18
  274. package/lib/tree/bool.d.ts.map +0 -1
  275. package/lib/tree/bool.js +0 -28
  276. package/lib/tree/bool.js.map +0 -1
  277. package/lib/tree/call.d.ts +0 -66
  278. package/lib/tree/call.d.ts.map +0 -1
  279. package/lib/tree/call.js +0 -306
  280. package/lib/tree/call.js.map +0 -1
  281. package/lib/tree/collection.d.ts +0 -30
  282. package/lib/tree/collection.d.ts.map +0 -1
  283. package/lib/tree/collection.js +0 -37
  284. package/lib/tree/collection.js.map +0 -1
  285. package/lib/tree/color.d.ts +0 -101
  286. package/lib/tree/color.d.ts.map +0 -1
  287. package/lib/tree/color.js +0 -513
  288. package/lib/tree/color.js.map +0 -1
  289. package/lib/tree/combinator.d.ts +0 -13
  290. package/lib/tree/combinator.d.ts.map +0 -1
  291. package/lib/tree/combinator.js +0 -12
  292. package/lib/tree/combinator.js.map +0 -1
  293. package/lib/tree/comment.d.ts +0 -20
  294. package/lib/tree/comment.d.ts.map +0 -1
  295. package/lib/tree/comment.js +0 -19
  296. package/lib/tree/comment.js.map +0 -1
  297. package/lib/tree/condition.d.ts +0 -31
  298. package/lib/tree/condition.d.ts.map +0 -1
  299. package/lib/tree/condition.js +0 -103
  300. package/lib/tree/condition.js.map +0 -1
  301. package/lib/tree/control.d.ts +0 -104
  302. package/lib/tree/control.d.ts.map +0 -1
  303. package/lib/tree/control.js +0 -430
  304. package/lib/tree/control.js.map +0 -1
  305. package/lib/tree/declaration-custom.d.ts +0 -18
  306. package/lib/tree/declaration-custom.d.ts.map +0 -1
  307. package/lib/tree/declaration-custom.js +0 -24
  308. package/lib/tree/declaration-custom.js.map +0 -1
  309. package/lib/tree/declaration-var.d.ts +0 -35
  310. package/lib/tree/declaration-var.d.ts.map +0 -1
  311. package/lib/tree/declaration-var.js +0 -63
  312. package/lib/tree/declaration-var.js.map +0 -1
  313. package/lib/tree/declaration.d.ts +0 -78
  314. package/lib/tree/declaration.d.ts.map +0 -1
  315. package/lib/tree/declaration.js +0 -286
  316. package/lib/tree/declaration.js.map +0 -1
  317. package/lib/tree/default-guard.d.ts +0 -15
  318. package/lib/tree/default-guard.d.ts.map +0 -1
  319. package/lib/tree/default-guard.js +0 -19
  320. package/lib/tree/default-guard.js.map +0 -1
  321. package/lib/tree/dimension.d.ts +0 -34
  322. package/lib/tree/dimension.d.ts.map +0 -1
  323. package/lib/tree/dimension.js +0 -294
  324. package/lib/tree/dimension.js.map +0 -1
  325. package/lib/tree/expression.d.ts +0 -25
  326. package/lib/tree/expression.d.ts.map +0 -1
  327. package/lib/tree/expression.js +0 -32
  328. package/lib/tree/expression.js.map +0 -1
  329. package/lib/tree/extend-list.d.ts +0 -23
  330. package/lib/tree/extend-list.d.ts.map +0 -1
  331. package/lib/tree/extend-list.js +0 -23
  332. package/lib/tree/extend-list.js.map +0 -1
  333. package/lib/tree/extend.d.ts +0 -47
  334. package/lib/tree/extend.d.ts.map +0 -1
  335. package/lib/tree/extend.js +0 -296
  336. package/lib/tree/extend.js.map +0 -1
  337. package/lib/tree/function.d.ts +0 -48
  338. package/lib/tree/function.d.ts.map +0 -1
  339. package/lib/tree/function.js +0 -74
  340. package/lib/tree/function.js.map +0 -1
  341. package/lib/tree/import-js.d.ts +0 -35
  342. package/lib/tree/import-js.d.ts.map +0 -1
  343. package/lib/tree/import-js.js +0 -45
  344. package/lib/tree/import-js.js.map +0 -1
  345. package/lib/tree/import-style.d.ts +0 -156
  346. package/lib/tree/import-style.d.ts.map +0 -1
  347. package/lib/tree/import-style.js +0 -566
  348. package/lib/tree/import-style.js.map +0 -1
  349. package/lib/tree/index.d.ts +0 -71
  350. package/lib/tree/index.d.ts.map +0 -1
  351. package/lib/tree/index.js.map +0 -1
  352. package/lib/tree/interpolated-reference.d.ts +0 -24
  353. package/lib/tree/interpolated-reference.d.ts.map +0 -1
  354. package/lib/tree/interpolated-reference.js +0 -37
  355. package/lib/tree/interpolated-reference.js.map +0 -1
  356. package/lib/tree/interpolated.d.ts +0 -62
  357. package/lib/tree/interpolated.d.ts.map +0 -1
  358. package/lib/tree/interpolated.js +0 -204
  359. package/lib/tree/interpolated.js.map +0 -1
  360. package/lib/tree/js-array.d.ts +0 -10
  361. package/lib/tree/js-array.d.ts.map +0 -1
  362. package/lib/tree/js-array.js +0 -10
  363. package/lib/tree/js-array.js.map +0 -1
  364. package/lib/tree/js-expr.d.ts +0 -23
  365. package/lib/tree/js-expr.d.ts.map +0 -1
  366. package/lib/tree/js-expr.js +0 -28
  367. package/lib/tree/js-expr.js.map +0 -1
  368. package/lib/tree/js-function.d.ts +0 -20
  369. package/lib/tree/js-function.d.ts.map +0 -1
  370. package/lib/tree/js-function.js +0 -16
  371. package/lib/tree/js-function.js.map +0 -1
  372. package/lib/tree/js-object.d.ts +0 -10
  373. package/lib/tree/js-object.d.ts.map +0 -1
  374. package/lib/tree/js-object.js +0 -10
  375. package/lib/tree/js-object.js.map +0 -1
  376. package/lib/tree/list.d.ts +0 -38
  377. package/lib/tree/list.d.ts.map +0 -1
  378. package/lib/tree/list.js +0 -83
  379. package/lib/tree/list.js.map +0 -1
  380. package/lib/tree/log.d.ts +0 -29
  381. package/lib/tree/log.d.ts.map +0 -1
  382. package/lib/tree/log.js +0 -56
  383. package/lib/tree/log.js.map +0 -1
  384. package/lib/tree/mixin.d.ts +0 -87
  385. package/lib/tree/mixin.d.ts.map +0 -1
  386. package/lib/tree/mixin.js +0 -112
  387. package/lib/tree/mixin.js.map +0 -1
  388. package/lib/tree/negative.d.ts +0 -17
  389. package/lib/tree/negative.d.ts.map +0 -1
  390. package/lib/tree/negative.js +0 -22
  391. package/lib/tree/negative.js.map +0 -1
  392. package/lib/tree/nil.d.ts +0 -30
  393. package/lib/tree/nil.d.ts.map +0 -1
  394. package/lib/tree/nil.js +0 -35
  395. package/lib/tree/nil.js.map +0 -1
  396. package/lib/tree/node-base.d.ts +0 -361
  397. package/lib/tree/node-base.d.ts.map +0 -1
  398. package/lib/tree/node-base.js +0 -930
  399. package/lib/tree/node-base.js.map +0 -1
  400. package/lib/tree/node.d.ts +0 -10
  401. package/lib/tree/node.d.ts.map +0 -1
  402. package/lib/tree/node.js +0 -45
  403. package/lib/tree/node.js.map +0 -1
  404. package/lib/tree/number.d.ts +0 -21
  405. package/lib/tree/number.d.ts.map +0 -1
  406. package/lib/tree/number.js +0 -27
  407. package/lib/tree/number.js.map +0 -1
  408. package/lib/tree/operation.d.ts +0 -26
  409. package/lib/tree/operation.d.ts.map +0 -1
  410. package/lib/tree/operation.js +0 -103
  411. package/lib/tree/operation.js.map +0 -1
  412. package/lib/tree/paren.d.ts +0 -19
  413. package/lib/tree/paren.d.ts.map +0 -1
  414. package/lib/tree/paren.js +0 -92
  415. package/lib/tree/paren.js.map +0 -1
  416. package/lib/tree/query-condition.d.ts +0 -17
  417. package/lib/tree/query-condition.d.ts.map +0 -1
  418. package/lib/tree/query-condition.js +0 -39
  419. package/lib/tree/query-condition.js.map +0 -1
  420. package/lib/tree/quoted.d.ts +0 -28
  421. package/lib/tree/quoted.d.ts.map +0 -1
  422. package/lib/tree/quoted.js +0 -75
  423. package/lib/tree/quoted.js.map +0 -1
  424. package/lib/tree/range.d.ts +0 -33
  425. package/lib/tree/range.d.ts.map +0 -1
  426. package/lib/tree/range.js +0 -47
  427. package/lib/tree/range.js.map +0 -1
  428. package/lib/tree/reference.d.ts +0 -76
  429. package/lib/tree/reference.d.ts.map +0 -1
  430. package/lib/tree/reference.js +0 -521
  431. package/lib/tree/reference.js.map +0 -1
  432. package/lib/tree/rest.d.ts +0 -15
  433. package/lib/tree/rest.d.ts.map +0 -1
  434. package/lib/tree/rest.js +0 -32
  435. package/lib/tree/rest.js.map +0 -1
  436. package/lib/tree/rules-raw.d.ts +0 -17
  437. package/lib/tree/rules-raw.d.ts.map +0 -1
  438. package/lib/tree/rules-raw.js +0 -37
  439. package/lib/tree/rules-raw.js.map +0 -1
  440. package/lib/tree/rules.d.ts +0 -262
  441. package/lib/tree/rules.d.ts.map +0 -1
  442. package/lib/tree/rules.js +0 -2359
  443. package/lib/tree/rules.js.map +0 -1
  444. package/lib/tree/ruleset.d.ts +0 -92
  445. package/lib/tree/ruleset.d.ts.map +0 -1
  446. package/lib/tree/ruleset.js +0 -528
  447. package/lib/tree/ruleset.js.map +0 -1
  448. package/lib/tree/selector-attr.d.ts +0 -31
  449. package/lib/tree/selector-attr.d.ts.map +0 -1
  450. package/lib/tree/selector-attr.js +0 -99
  451. package/lib/tree/selector-attr.js.map +0 -1
  452. package/lib/tree/selector-basic.d.ts +0 -24
  453. package/lib/tree/selector-basic.d.ts.map +0 -1
  454. package/lib/tree/selector-basic.js +0 -38
  455. package/lib/tree/selector-basic.js.map +0 -1
  456. package/lib/tree/selector-capture.d.ts +0 -23
  457. package/lib/tree/selector-capture.d.ts.map +0 -1
  458. package/lib/tree/selector-capture.js +0 -34
  459. package/lib/tree/selector-capture.js.map +0 -1
  460. package/lib/tree/selector-complex.d.ts +0 -40
  461. package/lib/tree/selector-complex.d.ts.map +0 -1
  462. package/lib/tree/selector-complex.js +0 -143
  463. package/lib/tree/selector-complex.js.map +0 -1
  464. package/lib/tree/selector-compound.d.ts +0 -16
  465. package/lib/tree/selector-compound.d.ts.map +0 -1
  466. package/lib/tree/selector-compound.js +0 -114
  467. package/lib/tree/selector-compound.js.map +0 -1
  468. package/lib/tree/selector-interpolated.d.ts +0 -23
  469. package/lib/tree/selector-interpolated.d.ts.map +0 -1
  470. package/lib/tree/selector-interpolated.js +0 -27
  471. package/lib/tree/selector-interpolated.js.map +0 -1
  472. package/lib/tree/selector-list.d.ts +0 -17
  473. package/lib/tree/selector-list.d.ts.map +0 -1
  474. package/lib/tree/selector-list.js +0 -174
  475. package/lib/tree/selector-list.js.map +0 -1
  476. package/lib/tree/selector-pseudo.d.ts +0 -42
  477. package/lib/tree/selector-pseudo.d.ts.map +0 -1
  478. package/lib/tree/selector-pseudo.js +0 -204
  479. package/lib/tree/selector-pseudo.js.map +0 -1
  480. package/lib/tree/selector-simple.d.ts +0 -5
  481. package/lib/tree/selector-simple.d.ts.map +0 -1
  482. package/lib/tree/selector-simple.js +0 -6
  483. package/lib/tree/selector-simple.js.map +0 -1
  484. package/lib/tree/selector.d.ts +0 -43
  485. package/lib/tree/selector.d.ts.map +0 -1
  486. package/lib/tree/selector.js +0 -56
  487. package/lib/tree/selector.js.map +0 -1
  488. package/lib/tree/sequence.d.ts +0 -43
  489. package/lib/tree/sequence.d.ts.map +0 -1
  490. package/lib/tree/sequence.js +0 -151
  491. package/lib/tree/sequence.js.map +0 -1
  492. package/lib/tree/tree.d.ts +0 -87
  493. package/lib/tree/tree.d.ts.map +0 -1
  494. package/lib/tree/tree.js +0 -2
  495. package/lib/tree/tree.js.map +0 -1
  496. package/lib/tree/url.d.ts +0 -18
  497. package/lib/tree/url.d.ts.map +0 -1
  498. package/lib/tree/url.js +0 -35
  499. package/lib/tree/url.js.map +0 -1
  500. package/lib/tree/util/__tests__/debug-log.d.ts +0 -1
  501. package/lib/tree/util/__tests__/debug-log.d.ts.map +0 -1
  502. package/lib/tree/util/__tests__/debug-log.js +0 -36
  503. package/lib/tree/util/__tests__/debug-log.js.map +0 -1
  504. package/lib/tree/util/calculate.d.ts +0 -3
  505. package/lib/tree/util/calculate.d.ts.map +0 -1
  506. package/lib/tree/util/calculate.js +0 -10
  507. package/lib/tree/util/calculate.js.map +0 -1
  508. package/lib/tree/util/cast.d.ts +0 -10
  509. package/lib/tree/util/cast.d.ts.map +0 -1
  510. package/lib/tree/util/cast.js +0 -87
  511. package/lib/tree/util/cast.js.map +0 -1
  512. package/lib/tree/util/cloning.d.ts +0 -4
  513. package/lib/tree/util/cloning.d.ts.map +0 -1
  514. package/lib/tree/util/cloning.js +0 -8
  515. package/lib/tree/util/cloning.js.map +0 -1
  516. package/lib/tree/util/collections.d.ts +0 -57
  517. package/lib/tree/util/collections.d.ts.map +0 -1
  518. package/lib/tree/util/collections.js +0 -136
  519. package/lib/tree/util/collections.js.map +0 -1
  520. package/lib/tree/util/compare.d.ts +0 -11
  521. package/lib/tree/util/compare.d.ts.map +0 -1
  522. package/lib/tree/util/compare.js +0 -89
  523. package/lib/tree/util/compare.js.map +0 -1
  524. package/lib/tree/util/extend-helpers.d.ts +0 -2
  525. package/lib/tree/util/extend-helpers.d.ts.map +0 -1
  526. package/lib/tree/util/extend-helpers.js +0 -2
  527. package/lib/tree/util/extend-helpers.js.map +0 -1
  528. package/lib/tree/util/extend-roots.d.ts +0 -37
  529. package/lib/tree/util/extend-roots.d.ts.map +0 -1
  530. package/lib/tree/util/extend-roots.js +0 -700
  531. package/lib/tree/util/extend-roots.js.map +0 -1
  532. package/lib/tree/util/extend-roots.old.d.ts +0 -132
  533. package/lib/tree/util/extend-roots.old.d.ts.map +0 -1
  534. package/lib/tree/util/extend-roots.old.js +0 -2272
  535. package/lib/tree/util/extend-roots.old.js.map +0 -1
  536. package/lib/tree/util/extend-trace-debug.d.ts +0 -13
  537. package/lib/tree/util/extend-trace-debug.d.ts.map +0 -1
  538. package/lib/tree/util/extend-trace-debug.js +0 -34
  539. package/lib/tree/util/extend-trace-debug.js.map +0 -1
  540. package/lib/tree/util/extend-walk.d.ts +0 -53
  541. package/lib/tree/util/extend-walk.d.ts.map +0 -1
  542. package/lib/tree/util/extend-walk.js +0 -881
  543. package/lib/tree/util/extend-walk.js.map +0 -1
  544. package/lib/tree/util/extend.d.ts +0 -218
  545. package/lib/tree/util/extend.d.ts.map +0 -1
  546. package/lib/tree/util/extend.js +0 -3182
  547. package/lib/tree/util/extend.js.map +0 -1
  548. package/lib/tree/util/find-extendable-locations.d.ts +0 -2
  549. package/lib/tree/util/find-extendable-locations.d.ts.map +0 -1
  550. package/lib/tree/util/find-extendable-locations.js +0 -2
  551. package/lib/tree/util/find-extendable-locations.js.map +0 -1
  552. package/lib/tree/util/format.d.ts +0 -20
  553. package/lib/tree/util/format.d.ts.map +0 -1
  554. package/lib/tree/util/format.js +0 -67
  555. package/lib/tree/util/format.js.map +0 -1
  556. package/lib/tree/util/is-node.d.ts +0 -13
  557. package/lib/tree/util/is-node.d.ts.map +0 -1
  558. package/lib/tree/util/is-node.js +0 -43
  559. package/lib/tree/util/is-node.js.map +0 -1
  560. package/lib/tree/util/print.d.ts +0 -80
  561. package/lib/tree/util/print.d.ts.map +0 -1
  562. package/lib/tree/util/print.js +0 -205
  563. package/lib/tree/util/print.js.map +0 -1
  564. package/lib/tree/util/process-leading-is.d.ts +0 -25
  565. package/lib/tree/util/process-leading-is.d.ts.map +0 -1
  566. package/lib/tree/util/process-leading-is.js +0 -364
  567. package/lib/tree/util/process-leading-is.js.map +0 -1
  568. package/lib/tree/util/recursion-helper.d.ts +0 -15
  569. package/lib/tree/util/recursion-helper.d.ts.map +0 -1
  570. package/lib/tree/util/recursion-helper.js +0 -43
  571. package/lib/tree/util/recursion-helper.js.map +0 -1
  572. package/lib/tree/util/regex.d.ts +0 -4
  573. package/lib/tree/util/regex.d.ts.map +0 -1
  574. package/lib/tree/util/regex.js +0 -4
  575. package/lib/tree/util/regex.js.map +0 -1
  576. package/lib/tree/util/registry-utils.d.ts +0 -192
  577. package/lib/tree/util/registry-utils.d.ts.map +0 -1
  578. package/lib/tree/util/registry-utils.js +0 -1214
  579. package/lib/tree/util/registry-utils.js.map +0 -1
  580. package/lib/tree/util/ruleset-trace.d.ts +0 -4
  581. package/lib/tree/util/ruleset-trace.d.ts.map +0 -1
  582. package/lib/tree/util/ruleset-trace.js +0 -14
  583. package/lib/tree/util/ruleset-trace.js.map +0 -1
  584. package/lib/tree/util/selector-compare.d.ts +0 -2
  585. package/lib/tree/util/selector-compare.d.ts.map +0 -1
  586. package/lib/tree/util/selector-compare.js +0 -2
  587. package/lib/tree/util/selector-compare.js.map +0 -1
  588. package/lib/tree/util/selector-match-core.d.ts +0 -184
  589. package/lib/tree/util/selector-match-core.d.ts.map +0 -1
  590. package/lib/tree/util/selector-match-core.js +0 -1603
  591. package/lib/tree/util/selector-match-core.js.map +0 -1
  592. package/lib/tree/util/selector-utils.d.ts +0 -30
  593. package/lib/tree/util/selector-utils.d.ts.map +0 -1
  594. package/lib/tree/util/selector-utils.js +0 -100
  595. package/lib/tree/util/selector-utils.js.map +0 -1
  596. package/lib/tree/util/serialize-helper.d.ts +0 -13
  597. package/lib/tree/util/serialize-helper.d.ts.map +0 -1
  598. package/lib/tree/util/serialize-helper.js +0 -387
  599. package/lib/tree/util/serialize-helper.js.map +0 -1
  600. package/lib/tree/util/serialize-types.d.ts +0 -9
  601. package/lib/tree/util/serialize-types.d.ts.map +0 -1
  602. package/lib/tree/util/serialize-types.js +0 -216
  603. package/lib/tree/util/serialize-types.js.map +0 -1
  604. package/lib/tree/util/should-operate.d.ts +0 -23
  605. package/lib/tree/util/should-operate.d.ts.map +0 -1
  606. package/lib/tree/util/should-operate.js +0 -46
  607. package/lib/tree/util/should-operate.js.map +0 -1
  608. package/lib/tree/util/sourcemap.d.ts +0 -7
  609. package/lib/tree/util/sourcemap.d.ts.map +0 -1
  610. package/lib/tree/util/sourcemap.js +0 -25
  611. package/lib/tree/util/sourcemap.js.map +0 -1
  612. package/lib/types/config.d.ts +0 -205
  613. package/lib/types/config.d.ts.map +0 -1
  614. package/lib/types/config.js +0 -2
  615. package/lib/types/config.js.map +0 -1
  616. package/lib/types/index.d.ts +0 -15
  617. package/lib/types/index.d.ts.map +0 -1
  618. package/lib/types/index.js +0 -3
  619. package/lib/types/index.js.map +0 -1
  620. package/lib/types/modes.d.ts.map +0 -1
  621. package/lib/types/modes.js +0 -2
  622. package/lib/types/modes.js.map +0 -1
  623. package/lib/types.d.ts +0 -61
  624. package/lib/types.d.ts.map +0 -1
  625. package/lib/types.js +0 -2
  626. package/lib/types.js.map +0 -1
  627. package/lib/use-webpack-resolver.d.ts +0 -9
  628. package/lib/use-webpack-resolver.d.ts.map +0 -1
  629. package/lib/use-webpack-resolver.js +0 -41
  630. package/lib/use-webpack-resolver.js.map +0 -1
  631. package/lib/visitor/index.d.ts +0 -136
  632. package/lib/visitor/index.d.ts.map +0 -1
  633. package/lib/visitor/index.js +0 -135
  634. package/lib/visitor/index.js.map +0 -1
  635. package/lib/visitor/less-visitor.d.ts +0 -7
  636. package/lib/visitor/less-visitor.d.ts.map +0 -1
  637. package/lib/visitor/less-visitor.js.map +0 -1
@@ -0,0 +1,226 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { Context } from '../../../context.js';
3
+ import { tryExtendSelector } from '../extend-core.js';
4
+ import {
5
+ rules,
6
+ ruleset,
7
+ extend,
8
+ el,
9
+ compound,
10
+ sellist,
11
+ sel,
12
+ co,
13
+ pseudo,
14
+ ExtendFlag,
15
+ type Ruleset
16
+ } from '../../index.js';
17
+
18
+ /**
19
+ * processExtends behavior is tested via the real eval flow: build AST as the parser would
20
+ * (rules with rulesets that contain extend() nodes), call root.eval(context), then assert.
21
+ * No manual context.root, context.extendRoots.registerRoot, or context.extends.push.
22
+ */
23
+ describe('processExtends function (eval flow)', () => {
24
+ describe('Basic extend processing', () => {
25
+ it('should extend a simple ruleset', async () => {
26
+ const root = rules([
27
+ ruleset({ selector: el('.foo'), rules: rules([]) }),
28
+ ruleset({
29
+ selector: el('.bar'),
30
+ rules: rules([extend({ target: el('.foo') })])
31
+ })
32
+ ]);
33
+ const context = new Context();
34
+ const evald = await root.eval(context);
35
+ const firstRuleset = evald.at(0, context) as Ruleset | undefined;
36
+ expect(firstRuleset?.getEffectiveSelector?.(false, context).valueOf()).toBe('.foo,.bar');
37
+ });
38
+
39
+ it('should handle multiple extends on same target', async () => {
40
+ const root = rules([
41
+ ruleset({ selector: el('.foo'), rules: rules([]) }),
42
+ ruleset({
43
+ selector: el('.bar'),
44
+ rules: rules([extend({ target: el('.foo') })])
45
+ }),
46
+ ruleset({
47
+ selector: el('.baz'),
48
+ rules: rules([extend({ target: el('.foo') })])
49
+ })
50
+ ]);
51
+ const context = new Context();
52
+ const evald = await root.eval(context);
53
+ const firstRuleset = evald.at(0, context) as Ruleset | undefined;
54
+ expect(firstRuleset?.getEffectiveSelector?.(false, context).valueOf()).toBe('.foo,.bar,.baz');
55
+ });
56
+
57
+ it('should skip self-referencing extends', async () => {
58
+ const root = rules([
59
+ ruleset({
60
+ selector: el('.foo'),
61
+ rules: rules([extend({ target: el('.foo') })])
62
+ })
63
+ ]);
64
+ const context = new Context();
65
+ const evald = await root.eval(context);
66
+ const firstRuleset = evald.at(0, context) as Ruleset | undefined;
67
+ expect(firstRuleset?.getEffectiveSelector?.(false, context).valueOf()).toBe('.foo');
68
+ });
69
+ });
70
+
71
+ describe('Extend chaining', () => {
72
+ it('should chain extends when extended selector matches another target', async () => {
73
+ const root = rules([
74
+ ruleset({ selector: el('.foo'), rules: rules([]) }),
75
+ ruleset({
76
+ selector: el('.bar'),
77
+ rules: rules([extend({ target: el('.foo') })])
78
+ }),
79
+ ruleset({
80
+ selector: el('.baz'),
81
+ rules: rules([extend({ target: el('.bar') })])
82
+ })
83
+ ]);
84
+ const context = new Context();
85
+ const evald = await root.eval(context);
86
+ const firstRuleset = evald.at(0, context) as Ruleset | undefined;
87
+ expect(firstRuleset?.getEffectiveSelector?.(false, context).valueOf()).toBe('.foo,.bar,.baz');
88
+ });
89
+ });
90
+
91
+ describe('Partial extends', () => {
92
+ it('should handle partial extends with all flag', async () => {
93
+ const targetSelector = compound([el('.a'), el('.b')]);
94
+ const extendSelector = el('.c');
95
+ const root = rules([
96
+ ruleset({
97
+ selector: targetSelector,
98
+ rules: rules([])
99
+ }),
100
+ ruleset({
101
+ selector: extendSelector,
102
+ rules: rules([extend({ target: el('.b'), flag: ExtendFlag.All })])
103
+ })
104
+ ]);
105
+ const context = new Context();
106
+ const evald = await root.eval(context);
107
+ const firstRuleset = evald.at(0, context) as Ruleset | undefined;
108
+ const expected = tryExtendSelector(
109
+ targetSelector.copy(true),
110
+ el('.b'),
111
+ extendSelector.copy(true),
112
+ true
113
+ );
114
+ expect(firstRuleset?.getEffectiveSelector?.(false, context).valueOf()).toBe(expected.value.valueOf());
115
+ });
116
+
117
+ it('should apply partial extends to the outer ruleset selector when partial is true (Less `all`)', async () => {
118
+ const targetSelector = sellist([
119
+ compound([el('.replace'), el('.replace')]),
120
+ sel([compound([el('.c'), el('.replace')]), co('+'), el('.replace')])
121
+ ]);
122
+ const extendSelector = el('.rep_ace');
123
+ const outerRules = rules([
124
+ ruleset({
125
+ selector: sellist([el('.replace'), el('.c')]),
126
+ rules: rules([])
127
+ })
128
+ ]);
129
+ const root = rules([
130
+ ruleset({
131
+ selector: targetSelector,
132
+ rules: outerRules
133
+ }),
134
+ ruleset({
135
+ selector: extendSelector,
136
+ rules: rules([extend({ target: el('.replace'), flag: ExtendFlag.All })])
137
+ })
138
+ ]);
139
+ const context = new Context();
140
+ const evald = await root.eval(context);
141
+ const outerRuleset = evald.at(0, context) as Ruleset | undefined;
142
+ const nestedRuleset = outerRuleset?.get('rules')?.value?.[0];
143
+ const expected = tryExtendSelector(
144
+ targetSelector.copy(true),
145
+ el('.replace'),
146
+ extendSelector.copy(true),
147
+ true
148
+ );
149
+ expect(outerRuleset?.getEffectiveSelector?.(false, context).valueOf()).toBe(expected.value.valueOf());
150
+ // Nested selectors stay defined and keep their existing structure.
151
+ const nestedSel = nestedRuleset?.selector?.valueOf() ?? '';
152
+ expect(nestedSel).toContain('.replace');
153
+ expect(nestedSel).toContain('.c');
154
+ expect(nestedSel.length).toBeGreaterThan(0);
155
+ });
156
+
157
+ it('should apply multiple partial extends in sequence', async () => {
158
+ const targetSelector = sellist([
159
+ sel([el('.foo'), co(' '), el('.bar')]),
160
+ sel([el('.foo'), co(' '), el('.baz')])
161
+ ]);
162
+ const firstExtend = sel([el('.ext1'), co(' '), el('.ext2')]);
163
+ const secondExtend = pseudo({ name: ':is', arg: sellist([el('.ext3'), el('.ext4')]) });
164
+ const root = rules([
165
+ ruleset({
166
+ selector: targetSelector,
167
+ rules: rules([])
168
+ }),
169
+ ruleset({
170
+ selector: firstExtend,
171
+ rules: rules([extend({ target: el('.foo'), flag: ExtendFlag.All })])
172
+ }),
173
+ ruleset({
174
+ selector: secondExtend,
175
+ rules: rules([extend({ target: el('.foo'), flag: ExtendFlag.All })])
176
+ })
177
+ ]);
178
+ const context = new Context();
179
+ const evald = await root.eval(context);
180
+ const firstRuleset = evald.at(0, context) as Ruleset | undefined;
181
+ const output = firstRuleset?.getEffectiveSelector?.(false, context).valueOf() ?? '';
182
+ expect(output).toContain('.ext1 .ext2');
183
+ expect(output).toContain('.ext3,.ext4');
184
+ expect(output).toContain('.bar');
185
+ expect(output).toContain('.baz');
186
+ });
187
+ });
188
+
189
+ describe('shouldSkipRuleset logic', () => {
190
+ it('should skip extending ruleset that contains the extend as a child', async () => {
191
+ // .foo { extend(.foo) } only - the extend node is inside .foo, so we must not modify .foo (self-modification guard)
192
+ const root = rules([
193
+ ruleset({
194
+ selector: el('.foo'),
195
+ rules: rules([extend({ target: el('.foo') })])
196
+ })
197
+ ]);
198
+ const context = new Context();
199
+ const evald = await root.eval(context);
200
+ const firstRuleset = evald.at(0, context) as Ruleset | undefined;
201
+ expect(firstRuleset?.getEffectiveSelector?.(false, context).valueOf()).toBe('.foo');
202
+ });
203
+ });
204
+
205
+ describe('Phase 2 iterative processing', () => {
206
+ it('should process extended rulesets in Phase 2', async () => {
207
+ const root = rules([
208
+ ruleset({ selector: el('.foo'), rules: rules([]) }),
209
+ ruleset({
210
+ selector: el('.bar'),
211
+ rules: rules([extend({ target: el('.foo') })])
212
+ }),
213
+ ruleset({
214
+ selector: el('.baz'),
215
+ rules: rules([extend({ target: el('.bar') })])
216
+ })
217
+ ]);
218
+ const context = new Context();
219
+ const evald = await root.eval(context);
220
+ const fooRuleset = evald.at(0, context) as Ruleset | undefined;
221
+ const barRuleset = evald.at(1, context) as Ruleset | undefined;
222
+ expect(fooRuleset?.getEffectiveSelector?.(false, context).valueOf()).toContain('.bar');
223
+ expect(barRuleset?.getEffectiveSelector?.(false, context).valueOf()).toContain('.baz');
224
+ });
225
+ });
226
+ });
@@ -0,0 +1,205 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { el, sel, sellist, compound, co, pseudo, attr, PseudoSelector, amp, rules, ruleset, any } from '../../index.js';
3
+ import { processLeadingIs } from '../process-leading-is.js';
4
+ import { isNode } from '../is-node.js';
5
+ import { N } from '../../node-type.js';
6
+ import type { Selector } from '../../selector.js';
7
+ import { Context } from '../../../context.js';
8
+ import { F_IMPLICIT_AMPERSAND } from '../../node.js';
9
+
10
+ /** PseudoSelector.create (Node.create) sets generated so processLeadingIs can unwrap. */
11
+ function generatedIs(selector: Selector) {
12
+ const p = (PseudoSelector as any).create({ name: ':is', arg: selector as any });
13
+ expect(p.generated, 'PseudoSelector.create must set generated').toBe(true);
14
+ return p as ReturnType<typeof pseudo>;
15
+ }
16
+
17
+ /** Stringify processLeadingIs result for toBeString comparison */
18
+ function out(result: Selector | Selector[]): string {
19
+ return Array.isArray(result) ? result.map(s => (s as Selector).valueOf()).join(', ') : (result as Selector).valueOf();
20
+ }
21
+
22
+ describe('processLeadingIs', () => {
23
+ describe('does not unwrap when :is is not generated', () => {
24
+ it('leaves non-generated :is(SelectorList) as-is', () => {
25
+ const list = sellist([el('.a'), el('.b')]);
26
+ const isPseudo = pseudo({ name: ':is', arg: list });
27
+ expect((isPseudo).generated).toBeFalsy();
28
+ const result = processLeadingIs(isPseudo);
29
+ expect(result).toBe(isPseudo);
30
+ expect(out(result as Selector)).toBeString(`:is(.a,.b)`);
31
+ });
32
+
33
+ it('leaves non-generated :is(simple) as-is', () => {
34
+ const isPseudo = pseudo({ name: ':is', arg: el('.x') });
35
+ const result = processLeadingIs(isPseudo);
36
+ expect(result).toBe(isPseudo);
37
+ expect(out(result as Selector)).toBeString(`:is(.x)`);
38
+ });
39
+ });
40
+
41
+ describe('single generated :is()', () => {
42
+ it('unwraps generated :is(simple) to the inner selector', () => {
43
+ const inner = el('.x');
44
+ const isPseudo = generatedIs(inner);
45
+ const result = processLeadingIs(isPseudo);
46
+ expect(Array.isArray(result)).toBe(false);
47
+ expect(out(result as Selector)).toBeString(`.x`);
48
+ });
49
+
50
+ it('unwraps generated :is(SelectorList) at top level to SelectorList when multiple items', () => {
51
+ const list = sellist([el('.a'), el('.b')]);
52
+ const isPseudo = generatedIs(list);
53
+ const result = processLeadingIs(isPseudo);
54
+ expect(Array.isArray(result)).toBe(false);
55
+ expect(out(result as Selector)).toBeString(`.a,.b`);
56
+ });
57
+
58
+ it('unwraps generated :is(SelectorList) at top level to single selector when one item', () => {
59
+ const list = sellist([el('.a')]);
60
+ const isPseudo = generatedIs(list);
61
+ const result = processLeadingIs(isPseudo);
62
+ expect(Array.isArray(result)).toBe(false);
63
+ expect(out(result as Selector)).toBeString(`.a`);
64
+ });
65
+
66
+ it('returns array when inSelectorList and generated :is(SelectorList)', () => {
67
+ const list = sellist([el('.a'), el('.b')]);
68
+ const isPseudo = generatedIs(list);
69
+ const result = processLeadingIs(isPseudo, { inSelectorList: true });
70
+ expect(Array.isArray(result)).toBe(true);
71
+ expect(out(result as Selector[])).toBeString(`.a, .b`);
72
+ });
73
+ });
74
+
75
+ describe('SelectorList', () => {
76
+ it('flattens list items that are generated :is(SelectorList) when inSelectorList', () => {
77
+ const item1 = el('.x');
78
+ const item2 = generatedIs(sellist([el('.a'), el('.b')]));
79
+ const list = sellist([item1, item2]);
80
+ const result = processLeadingIs(list, { inSelectorList: false });
81
+ expect(out(result as Selector)).toBeString(`.x,.a,.b`);
82
+ });
83
+
84
+ it('returns single selector when list has one item after processing', () => {
85
+ const inner = el('.only');
86
+ const isPseudo = generatedIs(inner);
87
+ const list = sellist([isPseudo]);
88
+ const result = processLeadingIs(list);
89
+ expect(Array.isArray(result)).toBe(false);
90
+ expect(out(result as Selector)).toBeString(`.only`);
91
+ });
92
+ });
93
+
94
+ describe('CompoundSelector with generated :is as first component', () => {
95
+ /**
96
+ * Same initial AST as Less/CSS parser for `* b { &[e] { } }`:
97
+ * - Parser: qualifiedRule → selectorList → (single) complexSelector for `* b` → [BasicSelector(*), Combinator(' '), BasicSelector(b)].
98
+ * selectorList returns the single item, so ruleset.selector = ComplexSelector (not SelectorList).
99
+ * - Parser: inner qualifiedRule → selectorList → (single) complexSelector for `&[e]` → compoundSelector → [Ampersand, AttributeSelector(e)].
100
+ * compoundSelector with 2 items returns CompoundSelector; complexSelector returns it; selectorList returns it.
101
+ * So we build the same: frame selector = sel([el('*'), co(' '), el('b')]) (ComplexSelector), inner = compound([amp(), attr({ name: 'e' })]) (CompoundSelector).
102
+ * Eval produces compound with first component :is(* b); ampersand sets .generated so processLeadingIs unwraps to * b[e].
103
+ */
104
+ it('accepts evaled &[e] with frame * b already materialized to * b[e] (same path as ruleset)', async () => {
105
+ const parentSelector = sel([el('*'), co(' '), el('b')]) as any;
106
+ const frameRuleset = ruleset({ selector: parentSelector, rules: rules([]) });
107
+ const innerSelector = compound([amp(), attr({ name: 'e' })]);
108
+ const context = new Context({ collapseNesting: true });
109
+ context.rulesetFrames.push(frameRuleset);
110
+ const evaled = await (innerSelector as any).eval(context);
111
+ expect(isNode(evaled, N.CompoundSelector)).toBe(true);
112
+ const first = (evaled as any).value[0];
113
+ expect(isNode(first, N.ComplexSelector)).toBe(true);
114
+ expect(out(evaled as Selector)).toBeString(`* b[e]`);
115
+ const result = processLeadingIs(evaled as Selector);
116
+ expect(out(result as Selector)).toBeString(`* b[e]`);
117
+ });
118
+
119
+ it('unwraps :is(complex) and merges suffix into last part of complex', () => {
120
+ const complex = sel([el('.menu'), co(' '), el('.menu')]);
121
+ const comp = compound([generatedIs(complex as any), el('li')]);
122
+ const result = processLeadingIs(comp);
123
+ expect(out(result as Selector)).toBeString(`.menu li.menu`);
124
+ });
125
+
126
+ it('unwraps :is(* b)[e] to * b[e] (complex parent + attribute suffix; css-3 nesting case)', () => {
127
+ const complex = sel([el('*'), co(' '), el('b')]);
128
+ const comp = compound([generatedIs(complex as any), attr({ name: 'e' })]);
129
+ const result = processLeadingIs(comp);
130
+ expect(out(result as Selector)).toBeString(`* b[e]`);
131
+ });
132
+
133
+ it('does not unwrap when :is arg is SelectorList', () => {
134
+ const list = sellist([el('.a'), el('.b')]);
135
+ const comp = compound([generatedIs(list), el('li')]);
136
+ const result = processLeadingIs(comp);
137
+ expect(result).toBe(comp);
138
+ expect(out(result as Selector)).toBeString(`:is(.a,.b)li`);
139
+ });
140
+ });
141
+
142
+ describe('ComplexSelector with generated :is as first visual component', () => {
143
+ it('unwraps :is(ComplexSelector) into complex components', () => {
144
+ const inner = sel([el('.menu'), co(' '), el('.menu')]);
145
+ const complex = sel([generatedIs(inner as any), co(' '), el('.menu'), co('>'), el('li')]);
146
+ const result = processLeadingIs(complex as any);
147
+ expect(out(result as Selector)).toBeString(`.menu .menu .menu>li`);
148
+ });
149
+
150
+ it('unwraps :is(simple) as first component to single selector + rest', () => {
151
+ const inner = el('.x');
152
+ const complex = sel([generatedIs(inner), co(' '), el('.y')]);
153
+ const result = processLeadingIs(complex as any);
154
+ expect(out(result as Selector)).toBeString(`.x .y`);
155
+ });
156
+
157
+ it('does not unwrap when :is arg is SelectorList', () => {
158
+ const list = sellist([el('.a'), el('.b')]);
159
+ const complex = sel([generatedIs(list), co(' '), el('.y')]);
160
+ const result = processLeadingIs(complex as any);
161
+ expect(result).toBe(complex);
162
+ expect(out(result as Selector)).toBeString(`:is(.a,.b) .y`);
163
+ });
164
+ });
165
+
166
+ describe('implicit ampersand + generated :is(SelectorList)', () => {
167
+ it('unwraps to selector list when shape is implicit-& + generated :is(list)', () => {
168
+ const ampNode = amp({ selectorContainer: { selector: el('.base') } });
169
+ (ampNode as any).addFlag(F_IMPLICIT_AMPERSAND);
170
+ const listArg = sellist([
171
+ sel([el('.base'), co(' '), el('.x')]),
172
+ sel([el('.base'), co(' '), el('.y')])
173
+ ]);
174
+ const selector = sel([ampNode, co(' '), generatedIs(listArg)]);
175
+ const result = processLeadingIs(selector as any);
176
+ expect(Array.isArray(result)).toBe(false);
177
+ expect(out(result as Selector)).toBeString(`.x,.y`);
178
+ });
179
+
180
+ it('removes generated :is(list) wrapper in non-header special case', () => {
181
+ const ampNode = amp({ selectorContainer: { selector: el('.base') } });
182
+ (ampNode as any).addFlag(F_IMPLICIT_AMPERSAND);
183
+ const listArg = sellist([
184
+ sel([el('.base'), co(' '), el('.x')]),
185
+ sel([el('.base'), co(' '), el('.y')])
186
+ ]);
187
+ const selector = sel([ampNode, co(' '), generatedIs(listArg), co(' '), el('.tail')]);
188
+ const result = processLeadingIs(selector as any);
189
+ expect(Array.isArray(result)).toBe(false);
190
+ expect(out(result as Selector)).not.toContain(':is(');
191
+ expect(out(result as Selector)).toContain('.tail');
192
+ });
193
+ });
194
+
195
+ describe('does not recurse into pseudo args', () => {
196
+ it('unwraps outer generated :is once; inner :is is returned as arg (not recursively unwrapped)', () => {
197
+ const innerIs = pseudo({ name: ':is', arg: el('.inner') });
198
+ innerIs.generated = true;
199
+ const outer = generatedIs(innerIs);
200
+ const result = processLeadingIs(outer);
201
+ expect(Array.isArray(result)).toBe(false);
202
+ expect(out(result as Selector)).toBeString(`:is(.inner)`);
203
+ });
204
+ });
205
+ });
@@ -0,0 +1,184 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { CallMap } from '../recursion-helper.js';
3
+ import { call, list, num, ref } from '../../index.js';
4
+
5
+ describe('CallMap', () => {
6
+ describe('add', () => {
7
+ it('should return true when the same call is added twice with undefined', () => {
8
+ const callMap = new CallMap();
9
+ const call1 = call({
10
+ name: ref('mixin'),
11
+ args: undefined
12
+ });
13
+
14
+ // First call with undefined - should return false
15
+ expect(callMap.add(call1, undefined)).toBe(false);
16
+
17
+ // Second call with undefined - should return true
18
+ expect(callMap.add(call1, undefined)).toBe(true);
19
+ });
20
+
21
+ it('should return false when different calls are added with undefined', () => {
22
+ const callMap = new CallMap();
23
+ const call1 = call({
24
+ name: ref('mixin1'),
25
+ args: undefined
26
+ });
27
+ const call2 = call({
28
+ name: ref('mixin2'),
29
+ args: undefined
30
+ });
31
+
32
+ // First call with undefined
33
+ expect(callMap.add(call1, undefined)).toBe(false);
34
+
35
+ // Different call with undefined - should return false
36
+ expect(callMap.add(call2, undefined)).toBe(false);
37
+ });
38
+
39
+ it('should return true when the same call is added twice with the same list instance', () => {
40
+ const callMap = new CallMap();
41
+ const list1 = list([num(1), num(2)]);
42
+ const call1 = call({
43
+ name: ref('mixin'),
44
+ args: list1.get('value') as any
45
+ });
46
+
47
+ // First call with list1
48
+ expect(callMap.add(call1, list1)).toBe(false);
49
+
50
+ // Second call with same list instance - should return true
51
+ expect(callMap.add(call1, list1)).toBe(true);
52
+ });
53
+
54
+ it('should return true when the same call is added with identical lists (different instances)', () => {
55
+ const callMap = new CallMap();
56
+ const list1 = list([num(1), num(2)]);
57
+ const list2 = list([num(1), num(2)]); // Same content, different instance
58
+ const call1 = call({
59
+ name: ref('mixin'),
60
+ args: list1.get('value') as any
61
+ });
62
+
63
+ // First call with list1
64
+ expect(callMap.add(call1, list1)).toBe(false);
65
+
66
+ // Second call with list2 (different instance, same value) - should return true
67
+ expect(callMap.add(call1, list2)).toBe(true);
68
+ });
69
+
70
+ it('should return false when the same call is added with different lists', () => {
71
+ const callMap = new CallMap();
72
+ const list1 = list([num(1), num(2)]);
73
+ const list2 = list([num(3), num(4)]); // Different content
74
+ const call1 = call({
75
+ name: ref('mixin'),
76
+ args: list1.get('value') as any
77
+ });
78
+
79
+ // First call with list1
80
+ expect(callMap.add(call1, list1)).toBe(false);
81
+
82
+ // Second call with list2 (different content) - should return false
83
+ expect(callMap.add(call1, list2)).toBe(false);
84
+ });
85
+
86
+ it('should prevent a call from calling itself with the same params', () => {
87
+ const callMap = new CallMap();
88
+ const list1 = list([num(1), num(2)]);
89
+ const call1 = call({
90
+ name: ref('mixin'),
91
+ args: list1.get('value') as any
92
+ });
93
+
94
+ // First call - should return false
95
+ expect(callMap.add(call1, list1)).toBe(false);
96
+
97
+ // Same call with same params - should return true (recursion detected)
98
+ expect(callMap.add(call1, list1)).toBe(true);
99
+ });
100
+
101
+ it('should prevent different calls from calling each other with the same params', () => {
102
+ const callMap = new CallMap();
103
+ const list1 = list([num(1), num(2)]);
104
+ const call1 = call({
105
+ name: ref('mixin1'),
106
+ args: list1.get('value') as any
107
+ });
108
+ const call2 = call({
109
+ name: ref('mixin2'),
110
+ args: list1.get('value') as any
111
+ });
112
+
113
+ // First call with list1
114
+ expect(callMap.add(call1, list1)).toBe(false);
115
+
116
+ // Different call with same params - should return false
117
+ // (each call tracks its own args separately)
118
+ expect(callMap.add(call2, list1)).toBe(false);
119
+
120
+ // But if call2 calls itself with same params, it should return true
121
+ expect(callMap.add(call2, list1)).toBe(true);
122
+ });
123
+ });
124
+
125
+ describe('delete', () => {
126
+ it('should remove the last entry for a call', () => {
127
+ const callMap = new CallMap();
128
+ const list1 = list([num(1), num(2)]);
129
+ const call1 = call({
130
+ name: ref('mixin'),
131
+ args: list1.get('value') as any
132
+ });
133
+
134
+ // Add once - this adds the entry to the set
135
+ callMap.add(call1, list1);
136
+
137
+ // Add again - this checks but doesn't add (only one entry exists)
138
+ expect(callMap.add(call1, list1)).toBe(true);
139
+
140
+ // Delete once - removes the only entry
141
+ expect(callMap.delete(call1)).toBe(true);
142
+
143
+ // Now should return false (no entries)
144
+ expect(callMap.add(call1, list1)).toBe(false);
145
+ });
146
+
147
+ it('should handle multiple entries for a call', () => {
148
+ const callMap = new CallMap();
149
+ const list1 = list([num(1), num(2)]);
150
+ const list2 = list([num(3), num(4)]);
151
+ const call1 = call({
152
+ name: ref('mixin'),
153
+ args: list1.get('value') as any
154
+ });
155
+
156
+ // Add first list
157
+ callMap.add(call1, list1);
158
+
159
+ // Manually add second list to the set (simulating multiple calls)
160
+ // Note: The current implementation doesn't add new args on subsequent calls,
161
+ // so we need to test the delete behavior with multiple entries differently
162
+ const set = (callMap as any)._callMap.get(call1);
163
+ if (set) {
164
+ set.push(list2);
165
+ }
166
+
167
+ // Delete once - should remove the last entry (list2)
168
+ expect(callMap.delete(call1)).toBe(true);
169
+
170
+ // Should still return true for list1
171
+ expect(callMap.add(call1, list1)).toBe(true);
172
+ });
173
+
174
+ it('should return false when deleting a non-existent call', () => {
175
+ const callMap = new CallMap();
176
+ const call1 = call({
177
+ name: ref('mixin'),
178
+ args: undefined
179
+ });
180
+
181
+ expect(callMap.delete(call1)).toBe(false);
182
+ });
183
+ });
184
+ });