@jesscss/core 2.0.0-alpha.4 → 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 -94
  258. package/lib/tree/ampersand.d.ts.map +0 -1
  259. package/lib/tree/ampersand.js +0 -269
  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,1045 @@
1
+ import { describe, it, expect, beforeEach, beforeAll } from 'vitest';
2
+ import {
3
+ rules,
4
+ ruleset,
5
+ sel,
6
+ el,
7
+ sellist,
8
+ extend,
9
+ ExtendFlag,
10
+ style,
11
+ quoted,
12
+ any,
13
+ atrule,
14
+ type Rules,
15
+ Node,
16
+ decl,
17
+ spaced,
18
+ comment
19
+ } from '../index.js';
20
+ import { Context } from '../../context.js';
21
+ import { resolve } from 'node:path';
22
+ import { createTestContext } from './import-style-test-helpers.js';
23
+
24
+ let context: Context;
25
+
26
+ describe('Extend Roots Registry', () => {
27
+ beforeEach(() => {
28
+ context = createTestContext();
29
+ });
30
+
31
+ describe('Basic extend roots', () => {
32
+ /**
33
+ * Test: Main stylesheet should create an extend root
34
+ * Extends within the same root should work
35
+ */
36
+ it('should create root extend root and allow extends within same root', async () => {
37
+ const node = rules([
38
+ ruleset({
39
+ selector: sellist([sel([el('.base')])]),
40
+ rules: rules([
41
+ decl({ name: 'color', value: spaced([any('red')]) })
42
+ ])
43
+ }),
44
+ ruleset({
45
+ selector: sellist([sel([el('.child')])]),
46
+ rules: rules([
47
+ decl({ name: 'background-color', value: spaced([any('blue')]) }),
48
+ extend({
49
+ target: el('.base')
50
+ })
51
+ ])
52
+ })
53
+ ]);
54
+
55
+ const evald = await node.eval(context);
56
+ const css = evald.render(context);
57
+ expect(css).toBeString(`
58
+ .base,
59
+ .child {
60
+ color: red;
61
+ }
62
+ .child {
63
+ background-color: blue;
64
+ }
65
+ `);
66
+ });
67
+
68
+ it('invalidates ruleset cache so valueOf reflects new selector after extend', async () => {
69
+ const targetRuleset = ruleset({
70
+ selector: sellist([sel([el('.base')])]),
71
+ rules: rules([
72
+ decl({ name: 'color', value: spaced([any('red')]) })
73
+ ])
74
+ });
75
+
76
+ const node = rules([
77
+ targetRuleset,
78
+ ruleset({
79
+ selector: sellist([sel([el('.ext')])]),
80
+ rules: rules([
81
+ extend({
82
+ target: el('.base'),
83
+ flag: ExtendFlag.Exact
84
+ })
85
+ ])
86
+ })
87
+ ]);
88
+
89
+ // Cache the initial selector string before extend runs
90
+ expect(targetRuleset.valueOf()).toBe('.base');
91
+
92
+ const evald = await node.eval(context);
93
+ const activeContext = new Context();
94
+ activeContext.renderKey = evald.renderKey;
95
+ const renderedTarget = evald.at(0, activeContext) as typeof targetRuleset;
96
+
97
+ // The extended selector is on the current render path.
98
+ expect(renderedTarget.valueOf(activeContext)).toBe('.base,.ext');
99
+ // Canonical valueOf() still returns the original selector.
100
+ expect(targetRuleset.valueOf()).toBe('.base');
101
+ });
102
+ });
103
+
104
+ describe('@import type roots', () => {
105
+ /**
106
+ * Test: @import type should use parent's root (no new root created)
107
+ * Extends in @import should work with parent's root
108
+ */
109
+ it('@import type should use parent root and allow extends', async () => {
110
+ const importedPath = resolve(process.cwd(), 'imported.jess');
111
+ context.sourceTrees.set(importedPath, rules([
112
+ ruleset({
113
+ selector: sellist([sel([el('.base')])]),
114
+ rules: rules([
115
+ decl({ name: 'margin', value: spaced([any('5px')]) })
116
+ ])
117
+ })
118
+ ]));
119
+
120
+ const node = rules([
121
+ style({
122
+ path: quoted(any('imported.jess'))
123
+ }, {
124
+ type: 'import'
125
+ }),
126
+ ruleset({
127
+ selector: sellist([sel([el('.child')])]),
128
+ rules: rules([
129
+ decl({ name: 'background-color', value: spaced([any('blue')]) }),
130
+ extend({
131
+ target: el('.base')
132
+ })
133
+ ])
134
+ })
135
+ ]);
136
+
137
+ const evald = await node.eval(context);
138
+ const css = evald.render(context);
139
+ expect(css).toBeString(`
140
+ .base,
141
+ .child {
142
+ margin: 5px;
143
+ }
144
+ .child {
145
+ background-color: blue;
146
+ }
147
+ `);
148
+ });
149
+
150
+ /**
151
+ * Test: Extends registered inside @import should use parent's root
152
+ */
153
+ it('extends inside @import should use parent root', async () => {
154
+ const importedPath = resolve(process.cwd(), 'imported.jess');
155
+ context.sourceTrees.set(importedPath, rules([
156
+ ruleset({
157
+ selector: sellist([sel([el('.base')])]),
158
+ rules: rules([
159
+ decl({ name: 'color', value: spaced([any('red')]) })
160
+ ])
161
+ }),
162
+ ruleset({
163
+ selector: sellist([sel([el('.child')])]),
164
+ rules: rules([
165
+ decl({ name: 'background-color', value: spaced([any('blue')]) }),
166
+ extend({
167
+ target: el('.base')
168
+ })
169
+ ])
170
+ })
171
+ ]));
172
+
173
+ const node = rules([
174
+ style({
175
+ path: quoted(any('imported.jess'))
176
+ }, {
177
+ type: 'import'
178
+ })
179
+ ]);
180
+
181
+ const evald = await node.eval(context);
182
+ const css = evald.render(context);
183
+ expect(css).toBeString(`
184
+ .base,
185
+ .child {
186
+ color: red;
187
+ }
188
+ .child {
189
+ background-color: blue;
190
+ }
191
+ `);
192
+ });
193
+ });
194
+
195
+ describe('@compose type roots', () => {
196
+ /**
197
+ * Test: @compose type should create new extend root
198
+ * Sibling compose roots CANNOT extend each other (compose creates boundaries)
199
+ */
200
+ it('sibling compose roots cannot extend each other (compose creates boundaries)', async () => {
201
+ const imported1Path = resolve(process.cwd(), 'imported1.jess');
202
+ context.sourceTrees.set(imported1Path, rules([
203
+ ruleset({
204
+ selector: sellist([sel([el('.base')])]),
205
+ rules: rules([])
206
+ })
207
+ ]));
208
+
209
+ const imported2Path = resolve(process.cwd(), 'imported2.jess');
210
+ context.sourceTrees.set(imported2Path, rules([
211
+ ruleset({
212
+ selector: sellist([sel([el('.base2')])]),
213
+ rules: rules([
214
+ decl({ name: 'padding', value: spaced([any('10px')]) })
215
+ ])
216
+ })
217
+ ]));
218
+
219
+ const node = rules([
220
+ style({
221
+ path: quoted(any('imported1.jess'))
222
+ }, {
223
+ type: 'compose',
224
+ importOptions: { mutable: true }
225
+ }),
226
+ style({
227
+ path: quoted(any('imported2.jess'))
228
+ }, {
229
+ type: 'compose',
230
+ importOptions: { mutable: true }
231
+ }),
232
+ ruleset({
233
+ selector: sellist([sel([el('.child')])]),
234
+ rules: rules([
235
+ decl({ name: 'background-color', value: spaced([any('blue')]) }),
236
+ extend({
237
+ target: el('.base')
238
+ })
239
+ ])
240
+ })
241
+ ]);
242
+
243
+ const evald = await node.eval(context);
244
+ const css = evald.render(context);
245
+ // Sibling compose roots cannot extend each other - .base should NOT be extended
246
+ expect(css).toBeString(`
247
+ .base2 {
248
+ padding: 10px;
249
+ }
250
+ .child {
251
+ background-color: blue;
252
+ }
253
+ `);
254
+ });
255
+
256
+ /**
257
+ * Test: Child compose root cannot extend parent (compose creates boundary)
258
+ * Should collect extendNotAccessible warning, not throw error
259
+ */
260
+ it('child compose root cannot extend parent (compose is a boundary) - collects extendNotAccessible warning', async () => {
261
+ const importedPath = resolve(process.cwd(), 'imported.jess');
262
+ context.sourceTrees.set(importedPath, rules([
263
+ ruleset({
264
+ selector: sellist([sel([el('.child')])]),
265
+ rules: rules([
266
+ decl({ name: 'background-color', value: spaced([any('blue')]) }),
267
+ extend({
268
+ target: el('.base')
269
+ })
270
+ ])
271
+ })
272
+ ]));
273
+
274
+ const node = rules([
275
+ ruleset({
276
+ selector: sellist([sel([el('.base')])]),
277
+ rules: rules([
278
+ decl({ name: 'color', value: spaced([any('red')]) })
279
+ ])
280
+ }),
281
+ style({
282
+ path: quoted(any('imported.jess'))
283
+ }, {
284
+ type: 'compose'
285
+ // Protected by default (not mutable)
286
+ })
287
+ ]);
288
+
289
+ // Should not throw - extendNotAccessible is now a warning
290
+ const evald = await node.eval(context);
291
+ expect(evald).toBeDefined();
292
+
293
+ // Should have collected a warning
294
+ expect(context.warnings.length).toBeGreaterThan(0);
295
+ const warning = context.warnings.find(w => w.code === 'extend/not-accessible');
296
+ expect(warning).toBeDefined();
297
+ expect(warning?.message).toContain('Extend target');
298
+ expect(warning?.message).toContain('not accessible');
299
+ });
300
+ });
301
+
302
+ describe('Protected boundaries', () => {
303
+ /**
304
+ * Test: Protected compose blocks all access, including to descendants
305
+ */
306
+ it('compose is protected by default (not mutable) - collects extendNotAccessible warning', async () => {
307
+ const importedPath = resolve(process.cwd(), 'imported.jess');
308
+ context.sourceTrees.set(importedPath, rules([
309
+ ruleset({
310
+ selector: sellist([sel([el('.base')])]),
311
+ rules: rules([
312
+ decl({ name: 'height', value: spaced([any('200px')]) })
313
+ ])
314
+ })
315
+ ]));
316
+
317
+ const node = rules([
318
+ style({
319
+ path: quoted(any('imported.jess'))
320
+ }, {
321
+ type: 'compose'
322
+ // No mutable: true, so compose is protected by default
323
+ }),
324
+ ruleset({
325
+ selector: sellist([sel([el('.child')])]),
326
+ rules: rules([
327
+ decl({ name: 'background-color', value: spaced([any('blue')]) }),
328
+ extend({
329
+ target: el('.base')
330
+ })
331
+ ])
332
+ })
333
+ ]);
334
+
335
+ // Should not throw - extendNotAccessible is now a warning
336
+ const evald = await node.eval(context);
337
+ expect(evald).toBeDefined();
338
+
339
+ // Should have collected a warning
340
+ expect(context.warnings.length).toBeGreaterThan(0);
341
+ const warning = context.warnings.find(w => w.code === 'extend/not-accessible');
342
+ expect(warning).toBeDefined();
343
+ expect(warning?.message).toContain('Extend target');
344
+ expect(warning?.message).toContain('not accessible');
345
+ });
346
+
347
+ /**
348
+ * Test: Protected compose blocks access even if child is non-protected
349
+ */
350
+ it('nested compose is also protected even if inner has mutable children - collects extendNotAccessible warning', async () => {
351
+ const imported1Path = resolve(process.cwd(), 'imported1.jess');
352
+ context.sourceTrees.set(imported1Path, rules([
353
+ ruleset({
354
+ selector: sellist([sel([el('.base')])]),
355
+ rules: rules([
356
+ decl({ name: 'opacity', value: spaced([any('0.5')]) })
357
+ ])
358
+ })
359
+ ]));
360
+
361
+ const imported2Path = resolve(process.cwd(), 'imported2.jess');
362
+ context.sourceTrees.set(imported2Path, rules([
363
+ style({
364
+ path: quoted(any('imported1.jess'))
365
+ }, {
366
+ type: 'compose',
367
+ importOptions: { mutable: true } // Inner compose is mutable
368
+ })
369
+ ]));
370
+
371
+ const node = rules([
372
+ style({
373
+ path: quoted(any('imported2.jess'))
374
+ }, {
375
+ type: 'compose'
376
+ // Outer compose is protected by default (no mutable: true)
377
+ }),
378
+ ruleset({
379
+ selector: sellist([sel([el('.child')])]),
380
+ rules: rules([
381
+ decl({ name: 'background-color', value: spaced([any('blue')]) }),
382
+ extend({
383
+ target: el('.base')
384
+ })
385
+ ])
386
+ })
387
+ ]);
388
+
389
+ // Should not throw - extendNotAccessible is now a warning
390
+ const evald = await node.eval(context);
391
+ expect(evald).toBeDefined();
392
+
393
+ // Should have collected a warning
394
+ expect(context.warnings.length).toBeGreaterThan(0);
395
+ const warning = context.warnings.find(w => w.code === 'extend/not-accessible');
396
+ expect(warning).toBeDefined();
397
+ expect(warning?.message).toContain('Extend target');
398
+ expect(warning?.message).toContain('not accessible');
399
+ });
400
+
401
+ /**
402
+ * Test: Only accessible selectors are extended, inaccessible ones throw errors
403
+ */
404
+ it('only accessible selector is extended when same selector exists behind immutability boundary', async () => {
405
+ const imported1Path = resolve(process.cwd(), 'imported1.jess');
406
+ context.sourceTrees.set(imported1Path, rules([
407
+ ruleset({
408
+ selector: sellist([sel([el('.base')])]),
409
+ rules: rules([
410
+ decl({ name: 'color', value: spaced([any('red')]) })
411
+ ])
412
+ })
413
+ ]));
414
+
415
+ const imported2Path = resolve(process.cwd(), 'imported2.jess');
416
+ context.sourceTrees.set(imported2Path, rules([
417
+ ruleset({
418
+ selector: sellist([sel([el('.base')])]),
419
+ rules: rules([
420
+ decl({ name: 'color', value: spaced([any('blue')]) })
421
+ ])
422
+ })
423
+ ]));
424
+
425
+ const node = rules([
426
+ ruleset({
427
+ selector: sellist([sel([el('.base')])]),
428
+ rules: rules([
429
+ decl({ name: 'color', value: spaced([any('green')]) })
430
+ ])
431
+ }),
432
+ style({
433
+ path: quoted(any('imported1.jess'))
434
+ }, {
435
+ type: 'import'
436
+ // Import type is accessible
437
+ }),
438
+ style({
439
+ path: quoted(any('imported2.jess'))
440
+ }, {
441
+ type: 'compose'
442
+ // Compose type is protected (not accessible)
443
+ }),
444
+ ruleset({
445
+ selector: sellist([sel([el('.child')])]),
446
+ rules: rules([
447
+ decl({ name: 'background-color', value: spaced([any('yellow')]) }),
448
+ extend({
449
+ target: el('.base')
450
+ })
451
+ ])
452
+ })
453
+ ]);
454
+
455
+ const evald = await node.eval(context);
456
+ const css = evald.render(context);
457
+ // Should extend .base from main root and imported1.jess (import type), but NOT imported2.jess (compose type)
458
+ expect(css).toBeString(`
459
+ .base,
460
+ .child {
461
+ color: green;
462
+ }
463
+ .base,
464
+ .child {
465
+ color: red;
466
+ }
467
+ .base {
468
+ color: blue;
469
+ }
470
+ .child {
471
+ background-color: yellow;
472
+ }
473
+ `);
474
+ });
475
+
476
+ /**
477
+ * Test: Extend collects warning when target not found (doesn't exist anywhere)
478
+ * Changed from error to warning for Less compatibility
479
+ */
480
+ it('extend collects extendNotFound warning when target does not exist', async () => {
481
+ const node = rules([
482
+ ruleset({
483
+ selector: sellist([sel([el('.child')])]),
484
+ rules: rules([
485
+ decl({ name: 'color', value: spaced([any('red')]) }),
486
+ extend({
487
+ target: el('.nonexistent')
488
+ })
489
+ ])
490
+ })
491
+ ]);
492
+
493
+ // Should not throw - extendNotFound is now a warning
494
+ const evald = await node.eval(context);
495
+ expect(evald).toBeDefined();
496
+
497
+ // Should have collected a warning
498
+ expect(context.warnings.length).toBeGreaterThan(0);
499
+ const warning = context.warnings.find(w => w.code === 'extend/not-found');
500
+ expect(warning).toBeDefined();
501
+ expect(warning?.message).toContain('Extend target');
502
+ expect(warning?.message).toContain('not found');
503
+ });
504
+
505
+ /**
506
+ * Test: Extend collects extendNotAccessible warning when target exists but is blocked by compose boundary
507
+ * Changed from error to warning for Less compatibility
508
+ */
509
+ it('extend collects extendNotAccessible warning when target exists but is blocked by compose boundary', async () => {
510
+ const importedPath = resolve(process.cwd(), 'imported.jess');
511
+ context.sourceTrees.set(importedPath, rules([
512
+ ruleset({
513
+ selector: sellist([sel([el('.base')])]),
514
+ rules: rules([
515
+ decl({ name: 'color', value: spaced([any('red')]) })
516
+ ])
517
+ })
518
+ ]));
519
+
520
+ const node = rules([
521
+ style({
522
+ path: quoted(any('imported.jess'))
523
+ }, {
524
+ type: 'compose'
525
+ // Protected by default
526
+ }),
527
+ ruleset({
528
+ selector: sellist([sel([el('.child')])]),
529
+ rules: rules([
530
+ decl({ name: 'background-color', value: spaced([any('blue')]) }),
531
+ extend({
532
+ target: el('.base')
533
+ })
534
+ ])
535
+ })
536
+ ]);
537
+
538
+ // Should not throw - extendNotAccessible is now a warning
539
+ const evald = await node.eval(context);
540
+ expect(evald).toBeDefined();
541
+
542
+ // Should have collected a warning
543
+ expect(context.warnings.length).toBeGreaterThan(0);
544
+ const warning = context.warnings.find(w => w.code === 'extend/not-accessible');
545
+ expect(warning).toBeDefined();
546
+ expect(warning?.message).toContain('Extend target');
547
+ expect(warning?.message).toContain('not accessible');
548
+ });
549
+ });
550
+
551
+ describe('At-rule boundaries', () => {
552
+ /**
553
+ * Test: Extends FROM inside @media cannot extend outside
554
+ */
555
+ it('extends from inside @media cannot extend outside - collects extendNotAccessible warning', async () => {
556
+ const node = rules([
557
+ ruleset({
558
+ selector: sellist([sel([el('.base')])]),
559
+ rules: rules([
560
+ decl({ name: 'color', value: spaced([any('red')]) })
561
+ ])
562
+ }),
563
+ atrule({
564
+ name: any('@media'),
565
+ prelude: any('(min-width: 600px)'),
566
+ rules: rules([
567
+ ruleset({
568
+ selector: sellist([sel([el('.child')])]),
569
+ rules: rules([
570
+ decl({ name: 'background-color', value: spaced([any('blue')]) }),
571
+ extend({
572
+ target: el('.base')
573
+ })
574
+ ])
575
+ })
576
+ ])
577
+ })
578
+ ]);
579
+
580
+ // Should not throw (extend from inside @media cannot reach root; we skip merge, optionally warn).
581
+ const evald = await node.eval(context);
582
+ expect(evald).toBeDefined();
583
+
584
+ // Root .base unchanged (no merge across @media). Extend only alters selectors; .child keeps only its own decls.
585
+ const css = evald.render(context);
586
+ expect(css).toBeString(`
587
+ .base {
588
+ color: red;
589
+ }
590
+ @media (min-width: 600px) {
591
+ .child {
592
+ background-color: blue;
593
+ }
594
+ }
595
+ `);
596
+ });
597
+
598
+ /**
599
+ * Test: Extends FROM inside @container cannot extend outside
600
+ */
601
+ it('extends from inside @container cannot extend outside - collects extendNotAccessible warning', async () => {
602
+ const node = rules([
603
+ ruleset({
604
+ selector: sellist([sel([el('.base')])]),
605
+ rules: rules([
606
+ decl({ name: 'color', value: spaced([any('red')]) })
607
+ ])
608
+ }),
609
+ atrule({
610
+ name: any('@container'),
611
+ prelude: any('(min-width: 600px)'),
612
+ rules: rules([
613
+ ruleset({
614
+ selector: sellist([sel([el('.child')])]),
615
+ rules: rules([
616
+ decl({ name: 'background-color', value: spaced([any('blue')]) }),
617
+ extend({
618
+ target: el('.base')
619
+ })
620
+ ])
621
+ })
622
+ ])
623
+ })
624
+ ]);
625
+
626
+ // Should not throw (extend from inside @container cannot reach root; extend does not copy decls, .child keeps only its own).
627
+ const evald = await node.eval(context);
628
+ expect(evald).toBeDefined();
629
+
630
+ const css = evald.render(context);
631
+ expect(css).toBeString(`
632
+ .base {
633
+ color: red;
634
+ }
635
+ @container (min-width: 600px) {
636
+ .child {
637
+ background-color: blue;
638
+ }
639
+ }
640
+ `);
641
+ });
642
+
643
+ /**
644
+ * Test: Extends FROM inside @supports cannot extend outside
645
+ */
646
+ it('extends from inside @supports cannot extend outside - collects extendNotAccessible warning', async () => {
647
+ const node = rules([
648
+ ruleset({
649
+ selector: sellist([sel([el('.base')])]),
650
+ rules: rules([
651
+ decl({ name: 'color', value: spaced([any('red')]) })
652
+ ])
653
+ }),
654
+ atrule({
655
+ name: any('@supports'),
656
+ prelude: any('(display: grid)'),
657
+ rules: rules([
658
+ ruleset({
659
+ selector: sellist([sel([el('.child')])]),
660
+ rules: rules([
661
+ decl({ name: 'background-color', value: spaced([any('blue')]) }),
662
+ extend({
663
+ target: el('.base')
664
+ })
665
+ ])
666
+ })
667
+ ])
668
+ })
669
+ ]);
670
+
671
+ // Should not throw (extend from inside @supports cannot reach root; extend does not copy decls, .child keeps only its own).
672
+ const evald = await node.eval(context);
673
+ expect(evald).toBeDefined();
674
+
675
+ const css = evald.render(context);
676
+ expect(css).toBeString(`
677
+ .base {
678
+ color: red;
679
+ }
680
+ @supports (display: grid) {
681
+ .child {
682
+ background-color: blue;
683
+ }
684
+ }
685
+ `);
686
+ });
687
+
688
+ /**
689
+ * Test: Extends FROM outside at-rule can extend into at-rule
690
+ */
691
+ it('extends from outside at-rule can extend into at-rule', async () => {
692
+ const node = rules([
693
+ atrule({
694
+ name: any('@media'),
695
+ prelude: any('(min-width: 600px)'),
696
+ rules: rules([
697
+ ruleset({
698
+ selector: sellist([sel([el('.base')])]),
699
+ rules: rules([
700
+ decl({ name: 'font-size', value: spaced([any('16px')]) })
701
+ ])
702
+ })
703
+ ])
704
+ }),
705
+ ruleset({
706
+ selector: sellist([sel([el('.child')])]),
707
+ rules: rules([
708
+ decl({ name: 'background-color', value: spaced([any('blue')]) }),
709
+ extend({
710
+ target: el('.base')
711
+ })
712
+ ])
713
+ })
714
+ ]);
715
+
716
+ const evald = await node.eval(context);
717
+ const css = evald.render(context);
718
+ expect(css).toBeString(`
719
+ @media (min-width: 600px) {
720
+ .base,
721
+ .child {
722
+ font-size: 16px;
723
+ }
724
+ }
725
+ .child {
726
+ background-color: blue;
727
+ }
728
+ `);
729
+ });
730
+
731
+ /**
732
+ * Test: Extends from inside at-rule can extend into nested at-rules
733
+ */
734
+ it('extends from inside at-rule can extend into nested at-rules', async () => {
735
+ const node = rules([
736
+ atrule({
737
+ name: any('@media'),
738
+ prelude: any('(min-width: 600px)'),
739
+ rules: rules([
740
+ atrule({
741
+ name: any('@supports'),
742
+ prelude: any('(display: grid)'),
743
+ rules: rules([
744
+ ruleset({
745
+ selector: sellist([sel([el('.base')])]),
746
+ rules: rules([
747
+ decl({ name: 'grid-template-columns', value: spaced([any('1fr 1fr')]) })
748
+ ])
749
+ })
750
+ ])
751
+ }, {
752
+
753
+ }),
754
+ ruleset({
755
+ selector: sellist([sel([el('.child')])]),
756
+ rules: rules([
757
+ decl({ name: 'display', value: spaced([any('block')]) }),
758
+ extend({
759
+ selector: sel([el('.child')]),
760
+ target: el('.base')
761
+ })
762
+ ])
763
+ })
764
+ ])
765
+ })
766
+ ]);
767
+
768
+ const evald = await node.eval(context);
769
+ const css = evald.render(context);
770
+ expect(css).toBeString(`
771
+ @media (min-width: 600px) {
772
+ @supports (display: grid) {
773
+ .base,
774
+ .child {
775
+ grid-template-columns: 1fr 1fr;
776
+ }
777
+ }
778
+ .child {
779
+ display: block;
780
+ }
781
+ }
782
+ `);
783
+ });
784
+ });
785
+
786
+ describe('@layer name sharing', () => {
787
+ /**
788
+ * Test: Layers with same name should share extend roots
789
+ */
790
+ it('layers with same name share extend roots', async () => {
791
+ const node = rules([
792
+ atrule({
793
+ name: any('@layer'),
794
+ prelude: any('one'),
795
+ rules: rules([
796
+ ruleset({
797
+ selector: sellist([sel([el('.base')])]),
798
+ rules: rules([
799
+ decl({ name: 'font-size', value: spaced([any('16px')]) })
800
+ ])
801
+ })
802
+ ])
803
+ }),
804
+ comment('/* second layer */'),
805
+ atrule({
806
+ name: any('@layer'),
807
+ prelude: any('one'),
808
+ rules: rules([
809
+ ruleset({
810
+ selector: sellist([sel([el('.child')])]),
811
+ rules: rules([
812
+ decl({ name: 'color', value: spaced([any('blue')]) }),
813
+ extend({
814
+ selector: sel([el('.child')]),
815
+ target: el('.base')
816
+ })
817
+ ])
818
+ })
819
+ ])
820
+ })
821
+ ]);
822
+
823
+ const evald = await node.eval(context);
824
+ const css = evald.render(context);
825
+ expect(css).toBeString(`
826
+ @layer one {
827
+ .base,
828
+ .child {
829
+ font-size: 16px;
830
+ }
831
+ }
832
+ /* second layer */
833
+ @layer one {
834
+ .child {
835
+ color: blue;
836
+ }
837
+ }
838
+ `);
839
+ });
840
+
841
+ /**
842
+ * Test: Anonymous layers do not share extend roots.
843
+ * TODO: Currently no warning is collected; root identity or allRootsForWarning path needs investigation.
844
+ */
845
+ it.skip('anonymous layers do not share extend roots', async () => {
846
+ const node = rules([
847
+ atrule({
848
+ name: any('@layer'),
849
+ // No prelude = anonymous
850
+ rules: rules([
851
+ ruleset({
852
+ selector: sellist([sel([el('.base')])]),
853
+ rules: rules([
854
+ decl({ name: 'font-size', value: spaced([any('16px')]) })
855
+ ])
856
+ })
857
+ ])
858
+ }),
859
+ comment('/* second anonymous layer */'),
860
+ atrule({
861
+ name: any('@layer'),
862
+ // No prelude = anonymous
863
+ rules: rules([
864
+ ruleset({
865
+ selector: sellist([sel([el('.child')])]),
866
+ rules: rules([
867
+ decl({ name: 'color', value: spaced([any('green')]) }),
868
+ extend({
869
+ selector: sel([el('.child')]),
870
+ target: el('.base')
871
+ })
872
+ ])
873
+ })
874
+ ])
875
+ })
876
+ ]);
877
+
878
+ // Anonymous layers do not share extend roots, so extend should collect warning
879
+ const evald = await node.eval(context);
880
+ expect(evald).toBeDefined();
881
+
882
+ // Should have collected a warning (either extendNotFound or extendNotAccessible)
883
+ expect(context.warnings.length).toBeGreaterThan(0);
884
+ const warning = context.warnings.find(w => w.code === 'extend/not-found' || w.code === 'extend/not-accessible');
885
+ expect(warning).toBeDefined();
886
+ });
887
+
888
+ /**
889
+ * Test: Nested layers concatenate names (one.two)
890
+ */
891
+ it('nested layers concatenate names', async () => {
892
+ const node = rules([
893
+ atrule({
894
+ name: any('@layer'),
895
+ prelude: any('one'),
896
+ rules: rules([
897
+ atrule({
898
+ name: any('@layer'),
899
+ prelude: any('two'),
900
+ rules: rules([
901
+ ruleset({
902
+ selector: sellist([sel([el('.base')])]),
903
+ rules: rules([
904
+ decl({ name: 'z-index', value: spaced([any('10')]) })
905
+ ])
906
+ })
907
+ ])
908
+ }, {
909
+
910
+ })
911
+ ])
912
+ }),
913
+ comment('/* second layer with same name */'),
914
+ atrule({
915
+ name: any('@layer'),
916
+ prelude: any('one.two'),
917
+ rules: rules([
918
+ ruleset({
919
+ selector: sellist([sel([el('.child')])]),
920
+ rules: rules([
921
+ decl({ name: 'width', value: spaced([any('100px')]) }),
922
+ extend({
923
+ target: el('.base')
924
+ })
925
+ ])
926
+ })
927
+ ])
928
+ })
929
+ ]);
930
+
931
+ const evald = await node.eval(context);
932
+ const css = evald.render(context);
933
+ expect(css).toBeString(`
934
+ @layer one {
935
+ @layer two {
936
+ .base,
937
+ .child {
938
+ z-index: 10;
939
+ }
940
+ }
941
+ }
942
+ /* second layer with same name */
943
+ @layer one.two {
944
+ .child {
945
+ width: 100px;
946
+ }
947
+ }
948
+ `);
949
+ });
950
+ });
951
+
952
+ describe('Accessible roots computation', () => {
953
+ /**
954
+ * Test: Self root is accessible
955
+ */
956
+ it('self root is accessible for extends', async () => {
957
+ const node = rules([
958
+ ruleset({
959
+ selector: sellist([sel([el('.base')])]),
960
+ rules: rules([
961
+ decl({
962
+ name: any('color'),
963
+ value: any('red')
964
+ })
965
+ ])
966
+ }),
967
+ ruleset({
968
+ selector: sellist([sel([el('.child')])]),
969
+ rules: rules([
970
+ extend({
971
+ target: el('.base')
972
+ }),
973
+ decl({
974
+ name: any('background'),
975
+ value: any('blue')
976
+ })
977
+ ])
978
+ })
979
+ ]);
980
+
981
+ const evald = await node.eval(context);
982
+ const css = evald.render(context);
983
+ expect(css).toBeString(`
984
+ .base,
985
+ .child {
986
+ color: red;
987
+ }
988
+ .child {
989
+ background: blue;
990
+ }
991
+ `);
992
+ });
993
+
994
+ /**
995
+ * Test: Children roots (if not protected) are accessible
996
+ */
997
+ it('children roots are accessible if mutable', async () => {
998
+ const importedPath = resolve(process.cwd(), 'imported.jess');
999
+ context.sourceTrees.set(importedPath, rules([
1000
+ ruleset({
1001
+ selector: sellist([sel([el('.base')])]),
1002
+ rules: rules([
1003
+ decl({
1004
+ name: any('color'),
1005
+ value: any('red')
1006
+ })
1007
+ ])
1008
+ })
1009
+ ]));
1010
+
1011
+ const node = rules([
1012
+ style({
1013
+ path: quoted(any('imported.jess'))
1014
+ }, {
1015
+ type: 'compose',
1016
+ importOptions: { mutable: true }
1017
+ }),
1018
+ ruleset({
1019
+ selector: sellist([sel([el('.child')])]),
1020
+ rules: rules([
1021
+ extend({
1022
+ target: el('.base')
1023
+ }),
1024
+ decl({
1025
+ name: any('background'),
1026
+ value: any('blue')
1027
+ })
1028
+ ])
1029
+ })
1030
+ ]);
1031
+
1032
+ const evald = await node.eval(context);
1033
+ const css = evald.render(context);
1034
+ expect(css).toBeString(`
1035
+ .base,
1036
+ .child {
1037
+ color: red;
1038
+ }
1039
+ .child {
1040
+ background: blue;
1041
+ }
1042
+ `);
1043
+ });
1044
+ });
1045
+ });