@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,564 @@
1
+ import {
2
+ AssignmentType,
3
+ Any,
4
+ Call,
5
+ Each,
6
+ For,
7
+ If,
8
+ JsFunction,
9
+ List,
10
+ Nil,
11
+ Paren,
12
+ While,
13
+ VarDeclaration,
14
+ decl,
15
+ expr,
16
+ list,
17
+ el,
18
+ ref,
19
+ rules,
20
+ ruleset,
21
+ sel,
22
+ vardecl
23
+ } from '../index.js';
24
+ import { Context } from '../../context.js';
25
+
26
+ function makePattern(bindingNames: string[], kind: 'block' | 'list' | 'sequence' | 'single' = 'block') {
27
+ const vars = bindingNames.map(name => new VarDeclaration({
28
+ name: new Any(name, { role: 'property' }),
29
+ value: new Nil()
30
+ }, { paramVar: true }));
31
+ if (kind === 'single') {
32
+ return vars[0]!;
33
+ }
34
+ return vars;
35
+ }
36
+
37
+ function makeLoop(
38
+ pattern: VarDeclaration | VarDeclaration[],
39
+ iterable: any,
40
+ loopRules = rules([
41
+ decl({ name: 'item', value: ref({ key: 'value' }, { type: 'variable' }) }),
42
+ decl({ name: 'key', value: ref({ key: 'key' }, { type: 'variable' }) }),
43
+ decl({ name: 'index', value: ref({ key: 'index' }, { type: 'variable' }) })
44
+ ])
45
+ ) {
46
+ return new For({
47
+ vars: pattern,
48
+ iterable,
49
+ rules: loopRules
50
+ });
51
+ }
52
+
53
+ describe('Control Nodes', () => {
54
+ it('evaluates $for with block pattern + expression iterable', async () => {
55
+ const context = new Context();
56
+ const pattern = makePattern(['value', 'key', 'index'], 'block');
57
+ const iterable = expr(list([new Any('a'), new Any('b')]));
58
+ const root = rules([makeLoop(pattern, iterable)]);
59
+ const evald = await root.eval(context);
60
+ expect(evald.render(context)).toContain('item: a');
61
+ expect(evald.render(context)).toContain('item: b');
62
+ expect(evald.render(context)).toContain('key: 1');
63
+ expect(evald.render(context)).toContain('key: 2');
64
+ expect(evald.render(context)).toContain('index: 1');
65
+ expect(evald.render(context)).toContain('index: 2');
66
+ });
67
+
68
+ it('proves one loop iteration allocates one runtime key over a canonical template', async () => {
69
+ const context = new Context();
70
+ const loop = makeLoop(
71
+ makePattern(['value'], 'single'),
72
+ list([new Any('a')]),
73
+ rules([decl({ name: 'item', value: ref({ key: 'value' }, { type: 'variable' }) })])
74
+ );
75
+
76
+ const canonicalBody = loop.get('rules');
77
+ const templateDecl = canonicalBody.at(0, context) as ReturnType<typeof decl>;
78
+ const root = rules([loop]);
79
+ const evald = await root.eval(context);
80
+ const css = evald.render(context);
81
+
82
+ expect(css).toContain('item: a;');
83
+ expect(context.renderCounter).toBe(1);
84
+ expect(canonicalBody.toTrimmedString()).toContain('item: $value;');
85
+ expect(templateDecl.get('value').toTrimmedString()).toBe('$value');
86
+ expect(canonicalBody.renderKey).toBeDefined();
87
+ });
88
+
89
+ it('proves three loop iterations allocate three runtime keys over one canonical template', async () => {
90
+ const context = new Context();
91
+ const loop = makeLoop(
92
+ makePattern(['value'], 'single'),
93
+ list([new Any('a'), new Any('b'), new Any('c')]),
94
+ rules([decl({ name: 'item', value: ref({ key: 'value' }, { type: 'variable' }) })])
95
+ );
96
+
97
+ const canonicalBody = loop.get('rules');
98
+ const templateDecl = canonicalBody.at(0, context) as ReturnType<typeof decl>;
99
+ const root = rules([loop]);
100
+ const evald = await root.eval(context);
101
+ const css = evald.render(context);
102
+
103
+ expect(css).toContain('item: a;');
104
+ expect(css).toContain('item: b;');
105
+ expect(css).toContain('item: c;');
106
+ expect(css.indexOf('item: a;')).toBeLessThan(css.indexOf('item: b;'));
107
+ expect(css.indexOf('item: b;')).toBeLessThan(css.indexOf('item: c;'));
108
+ expect(context.renderCounter).toBe(3);
109
+ expect(canonicalBody.toTrimmedString()).toContain('item: $value;');
110
+ expect(templateDecl.get('value').toTrimmedString()).toBe('$value');
111
+ });
112
+
113
+ it('proves short nested loop output keeps outer and inner iteration paths distinct and preserves outer lookup inside the inner loop', async () => {
114
+ const context = new Context();
115
+ const innerLoop = makeLoop(
116
+ makePattern(['inner'], 'single'),
117
+ list([new Any('1'), new Any('2')]),
118
+ rules([
119
+ decl({ name: 'outer', value: ref({ key: 'outer' }, { type: 'variable' }) }),
120
+ decl({ name: 'inner', value: ref({ key: 'inner' }, { type: 'variable' }) })
121
+ ])
122
+ );
123
+ const outerLoop = makeLoop(
124
+ makePattern(['outer'], 'single'),
125
+ list([new Any('a'), new Any('b')]),
126
+ rules([innerLoop])
127
+ );
128
+ const root = rules([outerLoop]);
129
+
130
+ const evald = await root.eval(context);
131
+ const css = evald.render(context);
132
+
133
+ expect(css).toContain('outer: a;');
134
+ expect(css).toContain('outer: b;');
135
+ expect(css).toContain('inner: 1;');
136
+ expect(css).toContain('inner: 2;');
137
+ expect(css.match(/outer: a;/g)).toHaveLength(2);
138
+ expect(css.match(/outer: b;/g)).toHaveLength(2);
139
+ expect(css).toMatch(
140
+ /outer: a;[\s\S]*inner: 1;[\s\S]*outer: a;[\s\S]*inner: 2;[\s\S]*outer: b;[\s\S]*inner: 1;[\s\S]*outer: b;[\s\S]*inner: 2;/
141
+ );
142
+ expect(context.renderCounter).toBe(6);
143
+ });
144
+
145
+ it('proves a nested $for can resolve the inner iterable from the current outer loop binding', async () => {
146
+ const context = new Context();
147
+ const innerLoop = makeLoop(
148
+ makePattern(['value'], 'single'),
149
+ ref({ key: 'row' }, { type: 'variable' }),
150
+ rules([
151
+ decl({ name: 'item', value: ref({ key: 'value' }, { type: 'variable' }) })
152
+ ])
153
+ );
154
+ const outerLoop = makeLoop(
155
+ makePattern(['row'], 'single'),
156
+ list([
157
+ list([new Any('a'), new Any('b')]),
158
+ list([new Any('c'), new Any('d')])
159
+ ]),
160
+ rules([innerLoop])
161
+ );
162
+ const root = rules([outerLoop]);
163
+
164
+ const evald = await root.eval(context);
165
+ const css = evald.render(context);
166
+
167
+ expect(css).toContain('item: a;');
168
+ expect(css).toContain('item: b;');
169
+ expect(css).toContain('item: c;');
170
+ expect(css).toContain('item: d;');
171
+ expect(css).toMatch(/item: a;[\s\S]*item: b;[\s\S]*item: c;[\s\S]*item: d;/);
172
+ expect(context.renderCounter).toBe(6);
173
+ });
174
+
175
+ it('proves a nested $for resolves the outer binding for the inner iterable, then shadows that binding inside the inner body', async () => {
176
+ const context = new Context();
177
+ const innerLoop = makeLoop(
178
+ makePattern(['value'], 'single'),
179
+ ref({ key: 'value' }, { type: 'variable' }),
180
+ rules([
181
+ decl({ name: 'item', value: ref({ key: 'value' }, { type: 'variable' }) })
182
+ ])
183
+ );
184
+ const outerLoop = makeLoop(
185
+ makePattern(['value', 'key'], 'block'),
186
+ list([
187
+ list([new Any('a'), new Any('b')]),
188
+ list([new Any('c'), new Any('d')])
189
+ ]),
190
+ rules([
191
+ decl({ name: 'outer', value: ref({ key: 'key' }, { type: 'variable' }) }),
192
+ innerLoop
193
+ ])
194
+ );
195
+ const root = rules([outerLoop]);
196
+
197
+ const evald = await root.eval(context);
198
+ const css = evald.render(context);
199
+
200
+ expect(css).toMatch(
201
+ /outer: 1;[\s\S]*item: a;[\s\S]*item: b;[\s\S]*outer: 2;[\s\S]*item: c;[\s\S]*item: d;/
202
+ );
203
+ expect(css).not.toContain('item: $value;');
204
+ expect(context.renderCounter).toBe(6);
205
+ });
206
+
207
+ it('proves outer loop bindings are restored after an inner $for exits', async () => {
208
+ const context = new Context();
209
+ const innerLoop = makeLoop(
210
+ makePattern(['value', 'key'], 'block'),
211
+ ref({ key: 'value' }, { type: 'variable' }),
212
+ rules([
213
+ decl({ name: 'inner', value: ref({ key: 'key' }, { type: 'variable' }) })
214
+ ])
215
+ );
216
+ const outerLoop = makeLoop(
217
+ makePattern(['value', 'key'], 'block'),
218
+ list([
219
+ list([new Any('a'), new Any('b')]),
220
+ list([new Any('c'), new Any('d')])
221
+ ]),
222
+ rules([
223
+ decl({ name: 'outer-before', value: ref({ key: 'key' }, { type: 'variable' }) }),
224
+ innerLoop,
225
+ decl({ name: 'outer-after', value: ref({ key: 'key' }, { type: 'variable' }) })
226
+ ])
227
+ );
228
+ const root = rules([outerLoop]);
229
+
230
+ const evald = await root.eval(context);
231
+ const css = evald.render(context);
232
+
233
+ expect(css).toMatch(
234
+ /outer-before: 1;[\s\S]*inner: 1;[\s\S]*inner: 2;[\s\S]*outer-after: 1;[\s\S]*outer-before: 2;[\s\S]*inner: 1;[\s\S]*inner: 2;[\s\S]*outer-after: 2;/
235
+ );
236
+ expect(context.renderCounter).toBe(6);
237
+ });
238
+
239
+ it('proves nested $for lookup can climb past an intermediate loop scope to reuse an outer iterable binding', async () => {
240
+ const context = new Context();
241
+ const innerLoop = makeLoop(
242
+ makePattern(['value'], 'single'),
243
+ ref({ key: 'rows' }, { type: 'variable' }),
244
+ rules([
245
+ decl({ name: 'inner', value: ref({ key: 'value' }, { type: 'variable' }) })
246
+ ])
247
+ );
248
+ const middleLoop = makeLoop(
249
+ makePattern(['row'], 'single'),
250
+ ref({ key: 'rows' }, { type: 'variable' }),
251
+ rules([
252
+ decl({ name: 'middle', value: ref({ key: 'row' }, { type: 'variable' }) }),
253
+ innerLoop
254
+ ])
255
+ );
256
+ const outerLoop = makeLoop(
257
+ makePattern(['rows'], 'single'),
258
+ list([list([new Any('a'), new Any('b')])]),
259
+ rules([middleLoop])
260
+ );
261
+ const root = rules([outerLoop]);
262
+
263
+ const evald = await root.eval(context);
264
+ const css = evald.render(context);
265
+
266
+ expect(css).toMatch(
267
+ /middle: a;[\s\S]*inner: a;[\s\S]*inner: b;[\s\S]*middle: b;[\s\S]*inner: a;[\s\S]*inner: b;/
268
+ );
269
+ expect(context.renderCounter).toBe(7);
270
+ });
271
+
272
+ it('evaluates $for with call iterable branch', async () => {
273
+ const context = new Context();
274
+ const root = rules([]);
275
+ root.register('function', new JsFunction({
276
+ name: 'mkList',
277
+ fn: () => list([new Any('x'), new Any('y')])
278
+ }));
279
+ const iterableCall = new Call({
280
+ name: ref({ key: 'mkList' }, { type: 'function' }),
281
+ args: list([])
282
+ });
283
+ root.push(makeLoop(makePattern(['value', 'key', 'index']), iterableCall));
284
+ const evald = await root.eval(context);
285
+ expect(evald.render(context)).toContain('item: x');
286
+ expect(evald.render(context)).toContain('item: y');
287
+ expect(evald.render(context)).toContain('key: 1');
288
+ expect(evald.render(context)).toContain('key: 2');
289
+ });
290
+
291
+ it('evaluates $for with rules iterable and skips non-declarations', async () => {
292
+ const context = new Context();
293
+ const iterableRules = rules([
294
+ decl({ name: 'one', value: new Any('red') }),
295
+ ruleset({
296
+ selector: sel([el('.skip')]) as any,
297
+ rules: rules([decl({ name: 'x', value: new Any('nope') })])
298
+ }),
299
+ decl({ name: 'two', value: new Any('blue') })
300
+ ]);
301
+ const loopRules = rules([
302
+ decl({ name: 'name', value: ref({ key: 'key' }, { type: 'variable' }) }),
303
+ decl({ name: 'value', value: ref({ key: 'value' }, { type: 'variable' }) })
304
+ ]);
305
+ const root = rules([makeLoop(makePattern(['value', 'key'], 'block'), iterableRules, loopRules)]);
306
+ const evald = await root.eval(context);
307
+ expect(evald.render(context)).toContain('name: one');
308
+ expect(evald.render(context)).toContain('name: two');
309
+ expect(evald.render(context)).toContain('value: red');
310
+ expect(evald.render(context)).toContain('value: blue');
311
+ expect(evald.render(context)).not.toContain('nope');
312
+ });
313
+
314
+ it('evaluates $for with scalar fallback iterable', async () => {
315
+ const context = new Context();
316
+ const root = rules([makeLoop(makePattern(['value', 'key', 'index']), new Any('solo'))]);
317
+ const evald = await root.eval(context);
318
+ expect(evald.render(context)).toContain('item: solo');
319
+ expect(evald.render(context)).toContain('key: 1');
320
+ expect(evald.render(context)).toContain('index: 1');
321
+ });
322
+
323
+ it('evaluates $for with paren-wrapped list iterable', async () => {
324
+ const context = new Context();
325
+ const iterable = new Paren(list([new Any('a'), new Any('b')]));
326
+ const root = rules([makeLoop(makePattern(['value', 'key', 'index']), iterable)]);
327
+ const evald = await root.eval(context);
328
+ expect(evald.render(context)).toContain('item: a');
329
+ expect(evald.render(context)).toContain('item: b');
330
+ expect(evald.render(context)).toContain('key: 1');
331
+ expect(evald.render(context)).toContain('key: 2');
332
+ });
333
+
334
+ it('supports list pattern bindings', async () => {
335
+ const context = new Context();
336
+ const loopRules = rules([
337
+ decl({ name: 'item', value: ref({ key: 'value' }, { type: 'variable' }) }),
338
+ decl({ name: 'key', value: ref({ key: 'key' }, { type: 'variable' }) })
339
+ ]);
340
+ const root = rules([makeLoop(makePattern(['value', 'key'], 'list'), list([new Any('a')]), loopRules)]);
341
+ const evald = await root.eval(context);
342
+ expect(evald.render(context)).toContain('item: a');
343
+ expect(evald.render(context)).toContain('key: 1');
344
+ });
345
+
346
+ it('supports sequence pattern bindings', async () => {
347
+ const context = new Context();
348
+ const loopRules = rules([
349
+ decl({ name: 'item', value: ref({ key: 'value' }, { type: 'variable' }) }),
350
+ decl({ name: 'key', value: ref({ key: 'key' }, { type: 'variable' }) })
351
+ ]);
352
+ const root = rules([makeLoop(makePattern(['value', 'key'], 'sequence'), list([new Any('a')]), loopRules)]);
353
+ const evald = await root.eval(context);
354
+ expect(evald.render(context)).toContain('item: a');
355
+ expect(evald.render(context)).toContain('key: 1');
356
+ });
357
+
358
+ it('supports single var pattern binding', async () => {
359
+ const context = new Context();
360
+ const loopRules = rules([
361
+ decl({ name: 'item', value: ref({ key: 'value' }, { type: 'variable' }) })
362
+ ]);
363
+ const root = rules([makeLoop(makePattern(['value'], 'single'), list([new Any('a')]), loopRules)]);
364
+ const evald = await root.eval(context);
365
+ expect(evald.render(context)).toContain('item: a');
366
+ });
367
+
368
+ it('creates For with single var binding', () => {
369
+ const singleVar = makePattern(['value'], 'single') as VarDeclaration;
370
+ const forNode = new For({ vars: singleVar, iterable: list([new Any('a')]), rules: rules([]) });
371
+ expect(forNode.get('vars')).toBe(singleVar);
372
+ });
373
+
374
+ it('forces public rulesVisibility for $if and $for rules', () => {
375
+ const privateRules = rules([], {
376
+ rulesVisibility: {
377
+ Declaration: 'private',
378
+ Ruleset: 'private',
379
+ VarDeclaration: 'private',
380
+ Mixin: 'private'
381
+ }
382
+ });
383
+ const ifNode = new If({
384
+ conditions: [new Any('true', { role: 'any' })],
385
+ bodies: [privateRules]
386
+ });
387
+ const forNode = new For({
388
+ vars: makePattern(['value'], 'single') as VarDeclaration,
389
+ iterable: list([new Any('a')]),
390
+ rules: rules([], {
391
+ rulesVisibility: {
392
+ Declaration: 'private',
393
+ Ruleset: 'private',
394
+ VarDeclaration: 'private',
395
+ Mixin: 'private'
396
+ }
397
+ })
398
+ });
399
+ expect(ifNode.get('bodies')[0]!.options.rulesVisibility.Declaration).toBe('public');
400
+ expect(ifNode.get('bodies')[0]!.options.rulesVisibility.Ruleset).toBe('public');
401
+ expect(ifNode.get('bodies')[0]!.options.rulesVisibility.VarDeclaration).toBe('public');
402
+ expect(ifNode.get('bodies')[0]!.options.rulesVisibility.Mixin).toBe('public');
403
+ expect(forNode.get('rules').options.rulesVisibility.Declaration).toBe('public');
404
+ expect(forNode.get('rules').options.rulesVisibility.Ruleset).toBe('public');
405
+ expect(forNode.get('rules').options.rulesVisibility.VarDeclaration).toBe('public');
406
+ expect(forNode.get('rules').options.rulesVisibility.Mixin).toBe('public');
407
+ });
408
+
409
+ it('evaluates and renders a cloned $for with a replaced iterable without mutating the canonical node', async () => {
410
+ const context = new Context();
411
+ const loop = makeLoop(makePattern(['value'], 'single'), list([new Any('a')]), rules([
412
+ decl({ name: 'item', value: ref({ key: 'value' }, { type: 'variable' }) })
413
+ ]));
414
+ const patchedIterable = list([new Any('patched')]);
415
+ const clonedLoop = loop.clone() as For;
416
+
417
+ clonedLoop.adopt(patchedIterable, context);
418
+ (clonedLoop as unknown as { iterable: List }).iterable = patchedIterable;
419
+
420
+ const evald = await clonedLoop.eval(context);
421
+
422
+ expect(evald.render(context)).toContain('item: patched');
423
+ expect(loop.toTrimmedString()).toContain('a');
424
+ expect(loop.get('iterable').toTrimmedString()).toBe('a');
425
+ expect(clonedLoop.get('iterable').toTrimmedString()).toBe('patched');
426
+ });
427
+
428
+ it('renders a cloned $if with replaced conditions and bodies without mutating the canonical node', () => {
429
+ const context = new Context();
430
+ const ifNode = new If({
431
+ conditions: [new Any('true', { role: 'any' })],
432
+ bodies: [rules([decl({ name: 'color', value: new Any('red') })])]
433
+ });
434
+ const clonedIf = ifNode.clone() as If;
435
+ const patchedCondition = new Any('false', { role: 'any' });
436
+ const patchedBody = rules([decl({ name: 'color', value: new Any('blue') })]);
437
+
438
+ clonedIf.adopt(patchedCondition, context);
439
+ clonedIf.adopt(patchedBody, context);
440
+ (clonedIf as unknown as { conditions: Any[] }).conditions = [patchedCondition];
441
+ (clonedIf as unknown as { bodies: ReturnType<typeof rules>[] }).bodies = [patchedBody];
442
+
443
+ expect(clonedIf.toTrimmedString({ context })).toContain('$if (false)');
444
+ expect(clonedIf.toTrimmedString({ context })).toContain('color: blue;');
445
+ expect(ifNode.toTrimmedString()).toContain('$if (true)');
446
+ expect(ifNode.toTrimmedString()).toContain('color: red;');
447
+ expect(ifNode.get('conditions')[0]!.toTrimmedString()).toBe('true');
448
+ expect(ifNode.get('bodies')[0]!.toTrimmedString()).toContain('color: red;');
449
+ });
450
+
451
+ it('renders a cloned $while with replaced condition and rules without mutating the canonical node', () => {
452
+ const context = new Context();
453
+ const whileNode = new While({
454
+ condition: new Any('true', { role: 'any' }),
455
+ rules: rules([decl({ name: 'color', value: new Any('red') })])
456
+ });
457
+ const clonedWhile = whileNode.clone() as While;
458
+ const patchedCondition = new Any('false', { role: 'any' });
459
+ const patchedRules = rules([decl({ name: 'color', value: new Any('blue') })]);
460
+
461
+ clonedWhile.adopt(patchedCondition, context);
462
+ clonedWhile.adopt(patchedRules, context);
463
+ (clonedWhile as unknown as { condition: Any }).condition = patchedCondition;
464
+ (clonedWhile as unknown as { rules: ReturnType<typeof rules> }).rules = patchedRules;
465
+
466
+ expect(clonedWhile.toTrimmedString({ context })).toContain('$while (false)');
467
+ expect(clonedWhile.toTrimmedString({ context })).toContain('color: blue;');
468
+ expect(whileNode.toTrimmedString()).toContain('$while (true)');
469
+ expect(whileNode.toTrimmedString()).toContain('color: red;');
470
+ expect(whileNode.get('condition').toTrimmedString()).toBe('true');
471
+ expect(whileNode.get('rules').toTrimmedString()).toContain('color: red;');
472
+ });
473
+
474
+ it('renders a cloned $each with replaced header and rules without mutating the canonical node', () => {
475
+ const context = new Context();
476
+ const eachNode = new Each({
477
+ header: expr(list([new Any('a')])),
478
+ rules: rules([decl({ name: 'color', value: new Any('red') })])
479
+ });
480
+ const clonedEach = eachNode.clone() as Each;
481
+ const patchedHeader = expr(list([new Any('patched')]));
482
+ const patchedRules = rules([decl({ name: 'color', value: new Any('blue') })]);
483
+
484
+ clonedEach.adopt(patchedHeader, context);
485
+ clonedEach.adopt(patchedRules, context);
486
+ (clonedEach as unknown as { header: ReturnType<typeof expr> }).header = patchedHeader;
487
+ (clonedEach as unknown as { rules: ReturnType<typeof rules> }).rules = patchedRules;
488
+
489
+ expect(clonedEach.toTrimmedString({ context })).toContain('$each $(patched)');
490
+ expect(clonedEach.toTrimmedString({ context })).toContain('color: blue;');
491
+ expect(eachNode.toTrimmedString()).toContain('$each $(a)');
492
+ expect(eachNode.toTrimmedString()).toContain('color: red;');
493
+ expect(eachNode.get('header').toTrimmedString()).toBe('$(a)');
494
+ expect(eachNode.get('rules').toTrimmedString()).toContain('color: red;');
495
+ });
496
+
497
+ it('keeps merged $for declaration values state-local during coalescing', async () => {
498
+ const context = new Context();
499
+ const loopRules = rules([
500
+ decl(
501
+ { name: 'padding', value: ref({ key: 'value' }, { type: 'variable' }) },
502
+ { normalizedFromAssign: AssignmentType.Add }
503
+ )
504
+ ]);
505
+ const loop = makeLoop(makePattern(['value'], 'single'), list([new Any('a'), new Any('b')]), loopRules);
506
+ const templateDecl = loop.get('rules').at(0, context) as ReturnType<typeof decl>;
507
+ const root = rules([loop]);
508
+
509
+ const evald = await root.eval(context);
510
+
511
+ expect(evald.toTrimmedString({ context })).toContain('padding: a, b;');
512
+ expect(templateDecl.toTrimmedString()).toContain('padding: $value');
513
+ });
514
+
515
+ it('reads a cloned normalizedFromAssign during $for coalescing without mutating the canonical declaration', async () => {
516
+ const context = new Context();
517
+ const loopRules = rules([
518
+ decl({ name: 'padding', value: ref({ key: 'value' }, { type: 'variable' }) })
519
+ ]);
520
+ const loop = makeLoop(makePattern(['value'], 'single'), list([new Any('a'), new Any('b')]), loopRules);
521
+ const templateDecl = loop.get('rules').at(0, context) as ReturnType<typeof decl>;
522
+ const clonedLoop = loop.clone(true) as For;
523
+ const clonedTemplateDecl = clonedLoop.get('rules').at(0, context) as ReturnType<typeof decl>;
524
+
525
+ clonedTemplateDecl.options = {
526
+ ...clonedTemplateDecl.options,
527
+ normalizedFromAssign: AssignmentType.Add
528
+ };
529
+
530
+ const evald = await clonedLoop.eval(context);
531
+ const css = evald.toTrimmedString({ context });
532
+
533
+ expect(css).toContain('padding: a, b;');
534
+ expect(String(templateDecl.options.normalizedFromAssign ?? '')).toBe('');
535
+ });
536
+
537
+ it('reads cloned rules-iterable declaration names and values during $for evaluation without mutating the canonical iterable', async () => {
538
+ const context = new Context();
539
+ const iterableRules = rules([
540
+ decl({ name: 'one', value: new Any('red') })
541
+ ]);
542
+ const iterDecl = iterableRules.at(0, context) as ReturnType<typeof decl>;
543
+ const loopRules = rules([
544
+ decl({ name: 'name', value: ref({ key: 'key' }, { type: 'variable' }) }),
545
+ decl({ name: 'value', value: ref({ key: 'value' }, { type: 'variable' }) })
546
+ ]);
547
+ const loop = makeLoop(makePattern(['value', 'key'], 'block'), iterableRules, loopRules);
548
+ const clonedLoop = loop.clone(true) as For;
549
+ const clonedIterDecl = (clonedLoop.get('iterable') as ReturnType<typeof rules>).at(0, context) as ReturnType<typeof decl>;
550
+
551
+ const patchedName = new Any('uno', { role: 'property' });
552
+ const patchedValue = new Any('green');
553
+ clonedIterDecl.adopt(patchedName, context);
554
+ clonedIterDecl.adopt(patchedValue, context);
555
+ (clonedIterDecl as unknown as { name: Any }).name = patchedName;
556
+ (clonedIterDecl as unknown as { value: Any }).value = patchedValue;
557
+
558
+ const evald = await clonedLoop.eval(context);
559
+
560
+ expect(evald.toTrimmedString({ context })).toContain('name: uno;');
561
+ expect(evald.toTrimmedString({ context })).toContain('value: green;');
562
+ expect(iterDecl.toTrimmedString()).toContain('one: red');
563
+ });
564
+ });