@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,1217 @@
1
+ import {
2
+ CALLER,
3
+ CANONICAL,
4
+ Node,
5
+ F_VISIBLE,
6
+ F_EXTENDED,
7
+ F_EXTEND_TARGET,
8
+ F_IMPLICIT_AMPERSAND,
9
+ F_NON_STATIC,
10
+ defineType,
11
+ type NodeOptions,
12
+ type OptionalLocation,
13
+ type RenderKey,
14
+ type NodeEdge
15
+ } from './node.js';
16
+ import { Rules } from './rules.js';
17
+ import type { Context, TreeContext } from '../context.js';
18
+ import { Nil } from './nil.js';
19
+ import { Bool } from './bool.js';
20
+ import type { Condition } from './condition.js';
21
+ import type { Selector } from './selector.js';
22
+ import { atIndex } from './util/collections.js';
23
+ import { isNode } from './util/is-node.js';
24
+ import { N } from './node-type.js';
25
+ import { Ampersand } from './ampersand.js';
26
+ import { ComplexSelector, type ComplexSelectorComponent } from './selector-complex.js';
27
+ import { SelectorList } from './selector-list.js';
28
+ import { type PrintOptions, type FinalPrintOptions, getPrintOptions } from './util/print.js';
29
+ import { type MaybePromise, pipe, isThenable } from '@jesscss/awaitable-pipe';
30
+ import type { AtRule } from './at-rule.js';
31
+ import { serializeRulesContainer, normalizeIndent, indent } from './util/serialize-helper.js';
32
+ import { getCurrentParentNode, getImplicitSelector as getImplicitSelectorUtil, getParentRuleset, hasExtendedSelector, hasSourceExtendWrapperParent, selectorHasAuthoredAmpersand } from './util/selector-utils.js';
33
+ import { addEdge } from './util/cursor.js';
34
+ import { processLeadingIs } from './util/process-leading-is.js';
35
+
36
+ export type RulesetValue = {
37
+ selector: Selector | Nil;
38
+ /**
39
+ * It's important that any Node that defines a Rules
40
+ * sets it to the `rules` property. This allows us to
41
+ * generalize nodes for the `frames` property in Context
42
+ */
43
+ rules: Rules;
44
+ guard?: Condition | Nil;
45
+ /**
46
+ * When this ruleset is extended, we store its selector before the first extend.
47
+ * Nested rulesets' implicit & (selectorContainer → parent value) use this when set, so they
48
+ * do not "see" the extended form (EXTEND_RULES §5: do not materialize ampersands
49
+ * that were not matched and extended).
50
+ */
51
+ selectorBeforeExtend?: Selector | Nil;
52
+ };
53
+
54
+ type RulesetOptions = NodeOptions & {
55
+ parentSelector?: Selector | Nil;
56
+ /** Own selector before parent resolution (getImplicitSelector); used by extend so nested rulesets extend .replace,.c not the resolved form. */
57
+ ownSelector?: Selector | Nil;
58
+ /** Hoisted at-rule wrapper already carries the caller selector; do not prepend the parent again in preEval. */
59
+ resolvedHoistWrapper?: boolean;
60
+ };
61
+
62
+ /** @todo - Fix typing */
63
+ type NarrowRulesetValue<T> = T extends RulesetValue ? T : RulesetValue;
64
+
65
+ export type RulesetChildData = {
66
+ selector: Selector | Nil;
67
+ rules: Rules;
68
+ guard: Condition | Nil | undefined;
69
+ selectorBeforeExtend: Selector | Nil | undefined;
70
+ /** Patched selector from extend — used by serialization instead of canonical selector. */
71
+ _extendedSelector: Selector | Nil | undefined;
72
+ frames: (Ruleset | AtRule)[] | undefined;
73
+ };
74
+
75
+ /**
76
+ * A qualified rule. This is historically called a "Ruleset"
77
+ * by older CSS documentation and by Less.
78
+ *
79
+ * @see https://developer.mozilla.org/en-US/docs/Web/CSS/Syntax#css_rulesets
80
+ *
81
+ * @example
82
+ * .box {
83
+ * color: black;
84
+ * }
85
+ */
86
+ export interface Ruleset {
87
+ type: 'Ruleset';
88
+ shortType: 'ruleset';
89
+ }
90
+
91
+ export class Ruleset<T = RulesetValue> extends Node<NarrowRulesetValue<T>, RulesetOptions, RulesetChildData> {
92
+ static override childKeys = ['selector', 'rules', 'guard', 'selectorBeforeExtend'] as const;
93
+
94
+ // Ruleset has preEval method but doesn't need to set flags - preEvaluated is tracked as boolean
95
+ private frames: (Ruleset | AtRule)[] | undefined;
96
+
97
+ selector!: Selector | Nil;
98
+ declare selectorEdge: NodeEdge<Selector | Nil> | undefined;
99
+ rules!: Rules;
100
+ declare rulesEdge: NodeEdge<Rules> | undefined;
101
+ guard: Condition | Nil | undefined;
102
+ declare guardEdge: NodeEdge<Condition | Nil | undefined> | undefined;
103
+ selectorBeforeExtend: Selector | Nil | undefined;
104
+ declare selectorBeforeExtendEdge: NodeEdge<Selector | Nil | undefined> | undefined;
105
+ /** Patched selector from extend — used by serialization instead of canonical selector. */
106
+ private _extendedSelector: Selector | Nil | undefined;
107
+ declare _extendedSelectorEdge: NodeEdge<Selector | Nil | undefined> | undefined;
108
+
109
+ constructor(value: NarrowRulesetValue<T>, options?: RulesetOptions, location?: OptionalLocation, treeContext?: TreeContext) {
110
+ super(value, options, location, treeContext);
111
+ this.selector = value.selector;
112
+ this.rules = value.rules;
113
+ this.guard = value.guard;
114
+ this.selectorBeforeExtend = value.selectorBeforeExtend;
115
+ if (this.selector instanceof Node) {
116
+ this.adopt(this.selector);
117
+ }
118
+ if (this.rules instanceof Node) {
119
+ this.adopt(this.rules);
120
+ }
121
+ if (this.guard instanceof Node) {
122
+ this.adopt(this.guard);
123
+ }
124
+ if (this.selectorBeforeExtend instanceof Node) {
125
+ this.adopt(this.selectorBeforeExtend);
126
+ }
127
+ this.allowRoot = true;
128
+ this.allowRuleRoot = true;
129
+ }
130
+
131
+ /**
132
+ * If this ruleset shares its value object with a descendant ruleset, give those
133
+ * descendants their own value so mutating this ruleset's value.selector does not
134
+ * overwrite the descendant's selector (e.g. .rep_ace nested ruleset case).
135
+ */
136
+ static ensureDescendantRulesetsHaveOwnValue(
137
+ ruleset: Ruleset,
138
+ sharedValue: RulesetValue
139
+ ): void {
140
+ const rules = ruleset.rules;
141
+ if (!rules || !isNode(rules, N.Rules)) {
142
+ return;
143
+ }
144
+ const children = (rules as Rules).value;
145
+ if (!Array.isArray(children)) {
146
+ return;
147
+ }
148
+ for (const child of children) {
149
+ if (!isNode(child, N.Ruleset)) {
150
+ continue;
151
+ }
152
+ const rs = child as Ruleset;
153
+ // With instance fields (no shared data object), shallow clones already
154
+ // have independent fields, so this identity check is always false.
155
+ // Kept for structural safety until full clone audit.
156
+ Ruleset.ensureDescendantRulesetsHaveOwnValue(rs, sharedValue);
157
+ }
158
+ }
159
+
160
+ static collapseRedundantGeneratedChildren(ruleset: Ruleset): void {
161
+ const rules = ruleset.rules;
162
+ if (!rules || !isNode(rules, N.Rules)) {
163
+ return;
164
+ }
165
+ const children = [...rules.value];
166
+ const normalized: Node[] = [];
167
+ for (const child of children) {
168
+ if (!isNode(child, N.Ruleset)) {
169
+ normalized.push(child);
170
+ continue;
171
+ }
172
+ const childRuleset = child as Ruleset;
173
+ Ruleset.collapseRedundantGeneratedChildren(childRuleset);
174
+ const shouldInline =
175
+ Boolean(ruleset.options?.generated)
176
+ && Boolean(childRuleset.options?.generated)
177
+ && String(ruleset.selector?.valueOf?.() ?? '') === String(childRuleset.selector?.valueOf?.() ?? '');
178
+ if (shouldInline) {
179
+ normalized.push(...childRuleset.rules.value);
180
+ continue;
181
+ }
182
+ normalized.push(childRuleset);
183
+ }
184
+ if (normalized.length !== rules.value.length || normalized.some((node, index) => node !== rules.value[index])) {
185
+ rules._setValueArray(normalized);
186
+ for (const child of normalized) {
187
+ rules.adopt(child);
188
+ }
189
+ }
190
+ }
191
+
192
+ isHoisted(options: PrintOptions) {
193
+ return this.hoistToRoot ?? options.collapseNesting ?? false;
194
+ }
195
+
196
+ protected _valueOf: string | undefined;
197
+
198
+ private _resolveRenderKey(context?: Context): RenderKey {
199
+ return context?.renderKey ?? context?.rulesContext?.renderKey ?? this.renderKey;
200
+ }
201
+
202
+ getOwnSelector(): Selector | Nil | undefined {
203
+ return this.options.ownSelector;
204
+ }
205
+
206
+ setOwnSelector(selector: Selector | Nil | undefined): void {
207
+ this.options = {
208
+ ...this.options,
209
+ ownSelector: selector
210
+ };
211
+ }
212
+
213
+ getSelector(renderKey?: RenderKey): Selector | Nil {
214
+ return renderKey !== undefined
215
+ ? this.selectorEdge?.get(renderKey) ?? this.selector
216
+ : this.selector;
217
+ }
218
+
219
+ private _getSelectorSourceNode(selector: Selector | Nil | undefined): Node | undefined {
220
+ if (!(selector instanceof Node)) {
221
+ return undefined;
222
+ }
223
+ return selector.sourceNode;
224
+ }
225
+
226
+ /**
227
+ * Transitional edge/cursor seam: enter the render-owned Rules container for
228
+ * this ruleset. This is intentionally explicit because it may wrap/adopt.
229
+ */
230
+ enterRules(context?: Context): Rules {
231
+ const renderKey = this._resolveRenderKey(context);
232
+ const rules = this.getRules(renderKey);
233
+ if (
234
+ renderKey !== undefined
235
+ && renderKey !== CANONICAL
236
+ && rules === this.rules
237
+ && this.rules.renderKey !== CANONICAL
238
+ && this.rules.renderKey !== renderKey
239
+ ) {
240
+ const wrappedRules = this.rules.createShallowBodyWrapper(undefined, renderKey);
241
+ addEdge(this, 'rules', renderKey, wrappedRules);
242
+ if (context && getCurrentParentNode(wrappedRules, { ...context, renderKey }) !== this) {
243
+ this.adopt(wrappedRules, { ...context, renderKey });
244
+ }
245
+ return wrappedRules;
246
+ }
247
+ if (rules !== this.rules) {
248
+ if (context && getCurrentParentNode(rules, context) !== this) {
249
+ this.adopt(rules, context);
250
+ }
251
+ return rules;
252
+ }
253
+ return rules.withRenderOwner(this, renderKey, context);
254
+ }
255
+
256
+ getRules(renderKey?: RenderKey): Rules {
257
+ return renderKey !== undefined
258
+ ? this.rulesEdge?.get(renderKey) ?? this.rules
259
+ : this.rules;
260
+ }
261
+
262
+ private _assignRules(rules: Rules, context: Context): void {
263
+ const renderKey = this._resolveRenderKey(context);
264
+ if (renderKey !== undefined && renderKey !== CANONICAL) {
265
+ this.rulesEdge?.delete(renderKey);
266
+ if (this.rulesEdge?.size === 0) {
267
+ this.rulesEdge = undefined;
268
+ }
269
+ }
270
+ this.rules = rules;
271
+ this.adopt(rules, context);
272
+ }
273
+
274
+ getGuard(renderKey?: RenderKey): Condition | Nil | undefined {
275
+ return renderKey !== undefined
276
+ ? this.guardEdge?.get(renderKey) ?? this.guard
277
+ : this.guard;
278
+ }
279
+
280
+ getSelectorBeforeExtend(renderKey?: RenderKey): Selector | Nil | undefined {
281
+ return renderKey !== undefined
282
+ ? this.selectorBeforeExtendEdge?.get(renderKey) ?? this.selectorBeforeExtend
283
+ : this.selectorBeforeExtend;
284
+ }
285
+
286
+ setSelectorBeforeExtend(selector: Selector | Nil | undefined, context: Context): void {
287
+ const renderKey = this._resolveRenderKey(context);
288
+ if (renderKey === undefined || renderKey === CANONICAL) {
289
+ this.selectorBeforeExtend = selector;
290
+ return;
291
+ }
292
+ if (selector instanceof Node) {
293
+ this.adopt(selector, { ...context, renderKey });
294
+ }
295
+ addEdge(this, 'selectorBeforeExtend', renderKey, selector as Selector | Nil);
296
+ }
297
+
298
+ getExtendedSelector(renderKey?: RenderKey): Selector | Nil | undefined {
299
+ return renderKey !== undefined
300
+ ? this._extendedSelectorEdge?.get(renderKey) ?? this._extendedSelector
301
+ : this._extendedSelector;
302
+ }
303
+
304
+ setExtendedSelector(selector: Selector | Nil | undefined, context?: Context): void {
305
+ const renderKey = context ? this._resolveRenderKey(context) : undefined;
306
+ if (renderKey === undefined || renderKey === CANONICAL) {
307
+ this._extendedSelector = selector;
308
+ this.invalidateSelectorValueCache();
309
+ return;
310
+ }
311
+ if (selector instanceof Node) {
312
+ this.adopt(selector, { ...context, renderKey });
313
+ }
314
+ addEdge(this, '_extendedSelector', renderKey, selector as Selector | Nil);
315
+ this.invalidateSelectorValueCache();
316
+ }
317
+
318
+ /**
319
+ * Returns the selector shape that should be printed for this ruleset.
320
+ *
321
+ * Nested rulesets keep rendering their local selector shape unless they are
322
+ * being serialized from root (`hoistToRoot`) or collapse nesting is enabled.
323
+ * In those cases, the selector must be recomposed against its parent.
324
+ */
325
+ getRenderableSelector(collapseNesting = this.treeContext?.opts?.collapseNesting ?? false, context?: Context): Selector | Nil {
326
+ const ownSelector = this.getOwnSelector();
327
+ if (
328
+ !hasSourceExtendWrapperParent(this)
329
+ && !this.hoistToRoot
330
+ && !collapseNesting
331
+ && ownSelector
332
+ && !(ownSelector instanceof Nil)
333
+ && this._hasAncestorRuleset(context)
334
+ ) {
335
+ return ownSelector as Selector;
336
+ }
337
+
338
+ return this.getEffectiveSelector(collapseNesting, context);
339
+ }
340
+
341
+ private _hasAncestorRuleset(context?: Context): boolean {
342
+ const seen = new Set<Node>();
343
+ const pending: Node[] = [];
344
+ const enqueue = (node: Node | undefined) => {
345
+ if (!node || seen.has(node)) {
346
+ return;
347
+ }
348
+ seen.add(node);
349
+ pending.push(node);
350
+ };
351
+
352
+ enqueue(getCurrentParentNode(this, context));
353
+ enqueue(this.parent);
354
+ for (const parent of this.parentEdges?.values?.() ?? []) {
355
+ enqueue(parent);
356
+ }
357
+
358
+ while (pending.length > 0) {
359
+ const current = pending.shift()!;
360
+ if (isNode(current, N.Ruleset)) {
361
+ return true;
362
+ }
363
+ enqueue(getCurrentParentNode(current, context));
364
+ enqueue(current.parent);
365
+ for (const parent of current.parentEdges?.values?.() ?? []) {
366
+ enqueue(parent);
367
+ }
368
+ }
369
+ return false;
370
+ }
371
+
372
+ /**
373
+ * Returns the selector that should be used for matching/rendering right now.
374
+ *
375
+ * For nested rulesets that keep a local `ownSelector`, this recomposes the
376
+ * selector against the current parent selector on demand instead of requiring
377
+ * eager mutation of `data.selector` after extends. Hoisted rulesets keep their
378
+ * concrete selector unchanged because they already serialize from root.
379
+ */
380
+ getEffectiveSelector(collapseNesting = this.treeContext?.opts?.collapseNesting ?? false, context?: Context): Selector | Nil {
381
+ // Use extend-patched selector if available, else canonical
382
+ const renderKey = this._resolveRenderKey(context);
383
+ const extendedSelector = this.getExtendedSelector(renderKey);
384
+ const selector = (extendedSelector ?? this.getSelector(renderKey)) as Selector | Nil;
385
+ if (!selector || selector instanceof Nil) {
386
+ return selector;
387
+ }
388
+
389
+ const ownSelector = this.getOwnSelector();
390
+ const parentRs = getParentRuleset(this, context);
391
+ if (
392
+ collapseNesting
393
+ && this.hoistToRoot
394
+ && ownSelector
395
+ && !(ownSelector instanceof Nil)
396
+ && isNode(ownSelector as Selector, N.SelectorList)
397
+ && isNode(selector as Selector, N.SelectorList)
398
+ && ownSelector.valueOf() !== selector.valueOf()
399
+ ) {
400
+ return selector;
401
+ }
402
+ if (
403
+ collapseNesting
404
+ && this.hoistToRoot
405
+ && ownSelector
406
+ && !(ownSelector instanceof Nil)
407
+ && Ruleset.isBareAmpersandSelector(ownSelector)
408
+ ) {
409
+ return selector;
410
+ }
411
+ const normalizeParentSelector = (parentSelector: Selector | Nil | undefined): Selector | Nil | undefined => {
412
+ if (
413
+ parentRs
414
+ && parentSelector
415
+ && !(parentSelector instanceof Nil)
416
+ && Ruleset.isBareAmpersandSelector(parentSelector)
417
+ ) {
418
+ const parentOwn = parentRs.getOwnSelector();
419
+ if (
420
+ parentOwn
421
+ && !(parentOwn instanceof Nil)
422
+ && Ruleset.isBareAmpersandSelector(parentOwn)
423
+ && parentRs.getSelector(parentRs._resolveRenderKey(context))
424
+ && !(parentRs.getSelector(parentRs._resolveRenderKey(context)) instanceof Nil)
425
+ && !Ruleset.isBareAmpersandSelector(parentRs.getSelector(parentRs._resolveRenderKey(context)))
426
+ ) {
427
+ return parentRs.getSelector(parentRs._resolveRenderKey(context));
428
+ }
429
+ }
430
+ return parentSelector;
431
+ };
432
+ const getComposedParentSelector = (): Selector | Nil | undefined => {
433
+ let parentSelector = normalizeParentSelector(parentRs?.getEffectiveSelector(collapseNesting, context));
434
+ if (
435
+ parentSelector
436
+ && !(parentSelector instanceof Nil)
437
+ && parentRs?.getSelectorBeforeExtend(parentRs._resolveRenderKey(context))
438
+ && Ruleset.hasReferenceBoundaryParent(parentRs, context)
439
+ ) {
440
+ parentSelector = Ruleset.filterReferenceVisibleSelectorItems(
441
+ parentSelector as Selector,
442
+ parentRs.getSelectorBeforeExtend(parentRs._resolveRenderKey(context))
443
+ );
444
+ }
445
+ return parentSelector;
446
+ };
447
+ const parentSelector = getComposedParentSelector();
448
+ if (
449
+ this.hoistToRoot
450
+ && extendedSelector
451
+ && !(extendedSelector instanceof Nil)
452
+ && ownSelector
453
+ && !(ownSelector instanceof Nil)
454
+ && selectorHasAuthoredAmpersand(ownSelector as Selector)
455
+ ) {
456
+ return selector;
457
+ }
458
+ if (
459
+ ownSelector
460
+ && !(ownSelector instanceof Nil)
461
+ && parentSelector
462
+ && !(parentSelector instanceof Nil)
463
+ && ownSelector.valueOf() !== selector.valueOf()
464
+ ) {
465
+ return getImplicitSelectorUtil(ownSelector as Selector, parentSelector as Selector, collapseNesting);
466
+ }
467
+
468
+ if (this.hoistToRoot) {
469
+ return selector;
470
+ }
471
+
472
+ return selector;
473
+ }
474
+
475
+ /** Used for equality comparison with other rulesets */
476
+ override valueOf(context?: Context) {
477
+ if (context) {
478
+ const collapseNesting = context.opts.collapseNesting ?? this.treeContext?.opts?.collapseNesting ?? false;
479
+ const renderKey = this._resolveRenderKey(context);
480
+ const selector = (
481
+ this.getExtendedSelector(renderKey)
482
+ || this.hoistToRoot
483
+ || collapseNesting === true
484
+ )
485
+ ? this.getEffectiveSelector(collapseNesting, context)
486
+ : this.getSelector(renderKey);
487
+ return selector instanceof Nil ? '' : (selector as Selector).valueOf();
488
+ }
489
+ if (this._valueOf !== undefined) {
490
+ return this._valueOf;
491
+ }
492
+ const selector = (
493
+ this._extendedSelector
494
+ || this.hoistToRoot
495
+ || this.treeContext?.opts?.collapseNesting === true
496
+ )
497
+ ? this.getEffectiveSelector()
498
+ : this.selector;
499
+ if (selector instanceof Nil) {
500
+ this._valueOf = '';
501
+ return this._valueOf;
502
+ }
503
+ this._valueOf = selector instanceof Nil ? '' : (selector as Selector).valueOf();
504
+ return this._valueOf;
505
+ }
506
+
507
+ /**
508
+ * Invalidate cached selector-based string value.
509
+ *
510
+ * `Ruleset.valueOf()` is used by serialization frame tracking; when an extend
511
+ * mutates `value.selector`, we must clear this cache so frame/header caching
512
+ * reflects the updated selector.
513
+ */
514
+ invalidateSelectorValueCache(): void {
515
+ this._valueOf = undefined;
516
+ }
517
+
518
+ override toTrimmedString(options?: PrintOptions): string {
519
+ options = getPrintOptions(options);
520
+ const opts = options as FinalPrintOptions;
521
+ if (
522
+ opts.referenceMode === true
523
+ && opts.referenceRenderEnabled !== false
524
+ && this.hoistToRoot
525
+ ) {
526
+ const ownSelector = this.getOwnSelector();
527
+ if (ownSelector && Ruleset.isBareAmpersandSelector(ownSelector)) {
528
+ return '';
529
+ }
530
+ }
531
+ return serializeRulesContainer(this, opts);
532
+ }
533
+
534
+ /**
535
+ * Render the opening of this ruleset (selector)
536
+ * @todo - Efficiently serialize the selector with and without comments?
537
+ */
538
+ /** Ensure every node in the selector has F_VISIBLE so toString() does not skip them (rep_ace bug).
539
+ * Do NOT add F_VISIBLE to implicit ampersands: they must stay invisible so nested output stays short. */
540
+ private static ensureSelectorVisible(sel: Selector | Nil): void {
541
+ if (!sel || sel instanceof Nil || typeof (sel as Node).addFlag !== 'function') {
542
+ return;
543
+ }
544
+ const n = sel as Node;
545
+ if (isNode(sel, N.Ampersand) && n.hasFlag(F_IMPLICIT_AMPERSAND)) {
546
+ return;
547
+ }
548
+ if (!n.hasFlag(F_VISIBLE)) {
549
+ n.addFlag(F_VISIBLE);
550
+ }
551
+ if (isNode(sel, N.SelectorList)) {
552
+ const list = sel as SelectorList;
553
+ for (const item of list.get('value')) {
554
+ Ruleset.ensureSelectorVisible(item);
555
+ }
556
+ return;
557
+ }
558
+ if (isNode(sel, N.ComplexSelector)) {
559
+ const comps = (sel as ComplexSelector).get('value');
560
+ for (const c of comps) {
561
+ Ruleset.ensureSelectorVisible(c as Selector);
562
+ }
563
+ return;
564
+ }
565
+ const v = 'value' in sel ? sel.value : undefined;
566
+ if (Array.isArray(v)) {
567
+ for (const c of v) {
568
+ Ruleset.ensureSelectorVisible(c);
569
+ }
570
+ }
571
+ }
572
+
573
+ private static materializeHoistedImplicitAmpersands(sel: Selector | Nil): Selector | Nil {
574
+ if (!sel || sel instanceof Nil) {
575
+ return sel;
576
+ }
577
+ const materialize = (node: Selector): Selector => {
578
+ if (isNode(node, N.Ampersand)) {
579
+ const amp = node as Ampersand;
580
+ const n = amp as unknown as Node;
581
+ if (n.hasFlag(F_IMPLICIT_AMPERSAND)) {
582
+ const resolved = amp.getResolvedSelector();
583
+ if (resolved && !(resolved instanceof Nil)) {
584
+ return resolved as Selector;
585
+ }
586
+ }
587
+ return node;
588
+ }
589
+ if (isNode(node, N.SelectorList)) {
590
+ const list = node as SelectorList;
591
+ return SelectorList.create(list.get('value').map(item => materialize(item as Selector))).inherit(node) as Selector;
592
+ }
593
+ if (isNode(node, N.ComplexSelector)) {
594
+ const complex = node as ComplexSelector;
595
+ const parts: ComplexSelectorComponent[] = [];
596
+ for (const part of complex.get('value')) {
597
+ if (isNode(part, N.Ampersand)) {
598
+ const amp = part as Ampersand;
599
+ const n = amp as unknown as Node;
600
+ if (n.hasFlag(F_IMPLICIT_AMPERSAND)) {
601
+ const resolved = amp.getResolvedSelector();
602
+ if (resolved && !(resolved instanceof Nil)) {
603
+ const repl = materialize(resolved as Selector);
604
+ if (isNode(repl, N.ComplexSelector)) {
605
+ parts.push(...(repl as ComplexSelector).get('value') as ComplexSelectorComponent[]);
606
+ } else {
607
+ parts.push(repl as ComplexSelectorComponent);
608
+ }
609
+ continue;
610
+ }
611
+ }
612
+ }
613
+ parts.push(materialize(part as Selector) as ComplexSelectorComponent);
614
+ }
615
+ return ComplexSelector.create(parts).inherit(node) as Selector;
616
+ }
617
+ const arr = 'value' in node ? node.value : undefined;
618
+ if (Array.isArray(arr)) {
619
+ const cloned = node.copy(true) as Selector & { value?: Selector[] };
620
+ cloned.value = arr.map(item => materialize(item as Selector));
621
+ return cloned as Selector;
622
+ }
623
+ return node;
624
+ };
625
+ const materialized = materialize(sel as Selector);
626
+ return processLeadingIs(materialized) as Selector;
627
+ }
628
+
629
+ static isBareAmpersandSelector(sel: Selector | Nil): boolean {
630
+ if (!sel || sel instanceof Nil) {
631
+ return false;
632
+ }
633
+ if (isNode(sel, N.Ampersand)) {
634
+ return (sel as Ampersand).isPlainAmpersand();
635
+ }
636
+ if (isNode(sel, N.CompoundSelector | N.ComplexSelector)) {
637
+ const items = (sel as unknown as { value?: unknown[] }).value;
638
+ if (!Array.isArray(items)) {
639
+ return false;
640
+ }
641
+ return items.length === 1
642
+ && isNode(items[0] as Node, N.Ampersand)
643
+ && (items[0] as Ampersand).isPlainAmpersand();
644
+ }
645
+ if (isNode(sel, N.SelectorList)) {
646
+ return (sel as SelectorList).get('value').every(
647
+ item => isNode(item, N.Ampersand) && (item as Ampersand).isPlainAmpersand()
648
+ );
649
+ }
650
+ return false;
651
+ }
652
+
653
+ private static hasReferenceBoundaryParent(node: Node, context?: Context): boolean {
654
+ const parent = getCurrentParentNode(node, context);
655
+ return Boolean(
656
+ parent
657
+ && isNode(parent, N.Rules)
658
+ && (parent as Rules).options?.referenceMode === true
659
+ );
660
+ }
661
+
662
+ static hasExtendedTopLevelSelector(sel: Selector | Nil): boolean {
663
+ return hasExtendedSelector(sel);
664
+ }
665
+
666
+ private static filterSelectorItems(
667
+ sel: Selector,
668
+ shouldKeep: (item: Selector) => boolean
669
+ ): Selector | Nil {
670
+ if (!isNode(sel, N.SelectorList)) {
671
+ return shouldKeep(sel) ? sel : new Nil();
672
+ }
673
+ const seen = new Set<string>();
674
+ const kept: Selector[] = [];
675
+ for (const item of (sel as SelectorList).get('value')) {
676
+ if (!shouldKeep(item)) {
677
+ continue;
678
+ }
679
+ const key = item.valueOf();
680
+ if (seen.has(key)) {
681
+ continue;
682
+ }
683
+ seen.add(key);
684
+ kept.push(item as Selector);
685
+ }
686
+ if (kept.length === 0) {
687
+ return new Nil();
688
+ }
689
+ if (kept.length === 1) {
690
+ return kept[0]!;
691
+ }
692
+ return SelectorList.create(kept).inherit(sel);
693
+ }
694
+
695
+ private static filterExtendedTopLevelSelectorItems(sel: Selector, context?: Context): Selector | Nil {
696
+ return Ruleset.filterSelectorItems(sel, item =>
697
+ (context ? item._hasFlag(F_EXTENDED, context) : item.hasFlag(F_EXTENDED))
698
+ && !(context ? item._hasFlag(F_EXTEND_TARGET, context) : item.hasFlag(F_EXTEND_TARGET))
699
+ );
700
+ }
701
+
702
+ private static filterReferenceVisibleSelectorItems(
703
+ current: Selector,
704
+ original?: Selector | Nil,
705
+ context?: Context
706
+ ): Selector | Nil {
707
+ if (!original || original instanceof Nil) {
708
+ return Ruleset.filterExtendedTopLevelSelectorItems(current, context);
709
+ }
710
+ const originalValues = new Set<string>();
711
+ if (isNode(original, N.SelectorList)) {
712
+ for (const item of (original as SelectorList).get('value')) {
713
+ originalValues.add(item.valueOf());
714
+ }
715
+ } else {
716
+ originalValues.add(original.valueOf());
717
+ }
718
+ const changedItems = Ruleset.filterSelectorItems(current, item =>
719
+ !originalValues.has(item.valueOf())
720
+ );
721
+ if (!(changedItems instanceof Nil)) {
722
+ return changedItems;
723
+ }
724
+ return Ruleset.filterSelectorItems(current, item =>
725
+ (context ? item._hasFlag(F_EXTENDED, context) : item.hasFlag(F_EXTENDED))
726
+ && !(context ? item._hasFlag(F_EXTEND_TARGET, context) : item.hasFlag(F_EXTEND_TARGET))
727
+ );
728
+ }
729
+
730
+ getHeaderString(options: FinalPrintOptions, withoutComments?: boolean): string {
731
+ const w = options.writer;
732
+ const renderKey = this.renderKey !== CANONICAL
733
+ ? this.renderKey
734
+ : this._resolveRenderKey(options.context);
735
+ const selector = this.getRenderableSelector(
736
+ options.collapseNesting,
737
+ options.context ? { ...options.context, renderKey } : options.context
738
+ );
739
+ const idt = indent(options.depth);
740
+
741
+ // Should never be called for Nil selectors (serializeRulesContainer guards this),
742
+ // but keep it safe for TypeScript and invariants.
743
+ if (selector instanceof Nil) {
744
+ return '';
745
+ }
746
+ if (withoutComments) {
747
+ options = { ...options, suppressComments: true };
748
+ }
749
+ let renderSelector: Selector | Nil = selector;
750
+ const ownSelector = this.getOwnSelector();
751
+ const currentSelector = this.getSelector(renderKey);
752
+ if (
753
+ this.hoistToRoot
754
+ && Ruleset.isBareAmpersandSelector(renderSelector)
755
+ && ownSelector
756
+ && !(ownSelector instanceof Nil)
757
+ && Ruleset.isBareAmpersandSelector(ownSelector)
758
+ && !Ruleset.isBareAmpersandSelector(currentSelector)
759
+ ) {
760
+ renderSelector = currentSelector;
761
+ }
762
+ if (this.hoistToRoot && options.depth === 0 && !(renderSelector instanceof Nil)) {
763
+ renderSelector = Ruleset.materializeHoistedImplicitAmpersands(renderSelector as Selector) as typeof selector;
764
+ }
765
+ if (
766
+ options.referenceMode === true
767
+ && options.referenceRenderEnabled === true
768
+ && !(renderSelector instanceof Nil)
769
+ ) {
770
+ const filteredReferenceSelector = Ruleset.filterReferenceVisibleSelectorItems(
771
+ renderSelector as Selector,
772
+ this.getSelectorBeforeExtend(renderKey),
773
+ options.context
774
+ ) as typeof renderSelector;
775
+ const rulesetExtended = options.context
776
+ ? this._hasFlag(F_EXTENDED, options.context)
777
+ : this.hasFlag(F_EXTENDED);
778
+ if (!(filteredReferenceSelector instanceof Nil)) {
779
+ renderSelector = filteredReferenceSelector;
780
+ } else if (!rulesetExtended) {
781
+ return '';
782
+ }
783
+ }
784
+ const prevReferenceFilterTargets = options.referenceFilterTargets === true;
785
+ const disableTargetFilteringForTopLevelList = (
786
+ (options.context ? this._hasFlag(F_EXTENDED, options.context) : this.hasFlag(F_EXTENDED))
787
+ && !(renderSelector instanceof Nil)
788
+ && isNode(renderSelector as Selector, N.SelectorList)
789
+ );
790
+ options.referenceFilterTargets = (
791
+ options.referenceMode === true
792
+ && options.referenceRenderEnabled === true
793
+ && !disableTargetFilteringForTopLevelList
794
+ );
795
+ Ruleset.ensureSelectorVisible(renderSelector);
796
+ const ctx = options.context;
797
+ const previousRenderKey = ctx?.renderKey;
798
+ if (ctx && renderKey !== undefined) {
799
+ ctx.renderKey = renderKey;
800
+ }
801
+ const selOut = w.capture(() => renderSelector.toString(options));
802
+ if (ctx) {
803
+ ctx.renderKey = previousRenderKey;
804
+ }
805
+ options.referenceFilterTargets = prevReferenceFilterTargets;
806
+ return normalizeIndent(selOut.replace(/\s+$/, '') + ' {', idt) + '\n';
807
+ }
808
+
809
+ override preEval(context: Context): MaybePromise<this> {
810
+ if (!this.preEvaluated) {
811
+ const node = this.clone(false, undefined, context);
812
+ node.preEvaluated = true;
813
+ const renderKey = node._resolveRenderKey(context);
814
+ const selectorText = String(this.getSelector(renderKey)?.valueOf?.() ?? '');
815
+ if (process.env.JESS_DEBUG_LOCK === 'throw-pre-ruleset' && selectorText.includes('.call-inner-lock-mixin')) {
816
+ throw new Error(`[lock-pre-ruleset] ${JSON.stringify({
817
+ selectorText,
818
+ parent: this.parent?.type,
819
+ sourceParent: this.sourceParent?.type,
820
+ renderKey: String(renderKey)
821
+ })}`);
822
+ }
823
+ // Index should already be assigned by parent Rules
824
+ node.sourceNode ??= this;
825
+ const rulesetOptions = node.options;
826
+ let rules = node.enterRules(context);
827
+ // On re-eval (e.g. mixin clone), use the pre-composition ownSelector so we
828
+ // compose from the authored selector, not the already-composed one.
829
+ let selector: Selector | Nil = rulesetOptions.ownSelector ?? node.getSelector(renderKey);
830
+ // Generated wrapper rulesets (e.g. implicit `& { ... }` created by AtRule hoisting)
831
+ // should not force var visibility to `private`, otherwise sibling vars inside the wrapper
832
+ // (like Less `@base`) become inaccessible.
833
+ if (!rulesetOptions.generated) {
834
+ if (rules.renderKey === CANONICAL) {
835
+ const wrappedRules = rules.createShallowBodyWrapper(context);
836
+ node.rules = wrappedRules;
837
+ node.adopt(wrappedRules, context);
838
+ rules = wrappedRules;
839
+ }
840
+ const nextRulesOptions = {
841
+ ...rules.options,
842
+ rulesVisibility: {
843
+ ...rules.options.rulesVisibility
844
+ }
845
+ };
846
+ if (context.leakyRules) {
847
+ nextRulesOptions.rulesVisibility.Mixin = 'public';
848
+ nextRulesOptions.rulesVisibility.VarDeclaration = 'optional';
849
+ } else {
850
+ nextRulesOptions.rulesVisibility.Mixin = 'private';
851
+ nextRulesOptions.rulesVisibility.VarDeclaration = 'private';
852
+ }
853
+ rules.options = nextRulesOptions;
854
+ }
855
+ const parentRuleset = context.rulesetFrames.at(-1);
856
+ const parentSelector = parentRuleset?.getSelector(parentRuleset._resolveRenderKey(context));
857
+ // Store own selector before parent resolution so extend can extend .replace,.c not the resolved form.
858
+ node.setOwnSelector(selector);
859
+ if (
860
+ !node.options.resolvedHoistWrapper
861
+ && parentSelector
862
+ && !(parentSelector instanceof Nil)
863
+ && !(selector instanceof Nil)
864
+ && parentRuleset
865
+ ) {
866
+ const collapseForComposition = Boolean(
867
+ context.opts.collapseNesting
868
+ && !selectorHasAuthoredAmpersand(selector as Selector)
869
+ );
870
+ selector = getImplicitSelectorUtil(
871
+ selector as Selector,
872
+ parentSelector as Selector,
873
+ collapseForComposition
874
+ );
875
+ {
876
+ const selectorSourceNode = node === this
877
+ ? selector.clone(false, undefined, context)
878
+ : selector;
879
+ if (selector instanceof Node) {
880
+ selector.sourceNode = selectorSourceNode;
881
+ }
882
+ }
883
+ }
884
+ // DO NOT evaluate guard here - guards are evaluated at call time in getFunctionFromMixins
885
+ // Just evaluate the selector
886
+ const ownSelector = node.getOwnSelector();
887
+ return pipe(
888
+ () => selector.eval(context),
889
+ (sel) => {
890
+ // If ownSelector has non-static children (e.g. interpolated attr values),
891
+ // evaluate it so extend matching uses the resolved form.
892
+ // Evaluate with collapseNesting=false so Ampersand nodes stay lazy
893
+ // (pointing at their parent container) rather than expanding into
894
+ // :is(parent). The combined selector was already correctly composed
895
+ // by getImplicitSelectorUtil; expanding & here corrupts the relative
896
+ // form and causes getEffectiveSelector to prepend the parent twice.
897
+ if (
898
+ ownSelector
899
+ && !isNode(ownSelector, N.Nil)
900
+ && ownSelector !== selector
901
+ ) {
902
+ const savedCollapseNesting = context.opts.collapseNesting;
903
+ context.opts.collapseNesting = false;
904
+ return pipe(
905
+ () => ownSelector.eval(context),
906
+ (evaledOwn) => {
907
+ context.opts.collapseNesting = savedCollapseNesting;
908
+ node.setOwnSelector(evaledOwn as Selector);
909
+ return sel;
910
+ }
911
+ );
912
+ }
913
+ return sel;
914
+ },
915
+ (sel) => {
916
+ if (isNode(sel as Node, N.Selector)) {
917
+ sel = processLeadingIs(sel as Selector) as Selector | Nil;
918
+ }
919
+ // If this ruleset shares its value with a descendant ruleset, give descendants
920
+ // their own value before we overwrite value.selector so they keep their selector.
921
+ Ruleset.ensureDescendantRulesetsHaveOwnValue(node as Ruleset, {} as RulesetValue);
922
+ // Store the evaluated selector - this is what will be in the frame
923
+ node.selector = sel as Selector | Nil;
924
+ if (sel instanceof Node) {
925
+ node.adopt(sel, context);
926
+ }
927
+ if (sel.hoistToRoot) {
928
+ node.hoistToRoot = true;
929
+ }
930
+ // Register to extend root's registry for extend lookups
931
+ const extendRoot = context.extendRoots.getCurrentExtendRoot();
932
+ if (extendRoot) {
933
+ extendRoot.register('ruleset', node as Ruleset);
934
+ // Keep a per-root registry list for visibility processing
935
+ context.extendRoots.registerRuleset(extendRoot, node as Ruleset);
936
+ }
937
+ // Depth-first: preEval child rules immediately so all nested rulesets/extends
938
+ // are registered in source order before we process extends.
939
+ // Push this ruleset to the frame so nested rulesets get the correct parent selector
940
+ // when building implicit selectors (e.g. .header-nav inside .header → .header .header-nav).
941
+ const childRules = node.enterRules(context);
942
+ if (childRules && !(childRules as unknown as Ruleset).preEvaluated) {
943
+ context.rulesetFrames.push(node as Ruleset);
944
+ if (extendRoot) {
945
+ context.extendRoots.registerRoot(childRules, extendRoot);
946
+ }
947
+ const preEvaldRules = childRules.preEval(context);
948
+ if (isThenable(preEvaldRules)) {
949
+ return (preEvaldRules as Promise<Rules>).then((rules) => {
950
+ context.rulesetFrames.pop();
951
+ node.rules = rules;
952
+ node.adopt(rules, context);
953
+ if (extendRoot && rules !== childRules) {
954
+ context.extendRoots.registerRoot(rules, extendRoot);
955
+ }
956
+ return node;
957
+ });
958
+ }
959
+ context.rulesetFrames.pop();
960
+ node._assignRules(preEvaldRules as Rules, context);
961
+ if (extendRoot && preEvaldRules !== childRules) {
962
+ context.extendRoots.registerRoot(preEvaldRules as Rules, extendRoot);
963
+ }
964
+ }
965
+ return node;
966
+ }
967
+ );
968
+ }
969
+ return this;
970
+ }
971
+
972
+ /** Attach an (invisible) ampersand to the selector(s) if it's not already there */
973
+ getImplicitSelector(parentSelector: Selector, collapseNesting = false) {
974
+ const selector = this.get('selector');
975
+ if (selector instanceof Nil) {
976
+ return selector;
977
+ }
978
+ return getImplicitSelectorUtil(selector, parentSelector, collapseNesting);
979
+ }
980
+
981
+ override clone(deep?: boolean, cloneFn?: (n: Node) => Node, ctx?: Context): this {
982
+ const priorSelectorParent = !deep && this.selector instanceof Node
983
+ ? this.selector.parent
984
+ : undefined;
985
+ const priorRulesParent = !deep && this.rules instanceof Node
986
+ ? this.rules.parent
987
+ : undefined;
988
+ const cloned = super.clone(deep, cloneFn, ctx) as this;
989
+ if (!deep) {
990
+ if (this.selector instanceof Node) {
991
+ (this.selector as unknown as { parent?: Node }).parent = priorSelectorParent;
992
+ }
993
+ if (this.rules instanceof Node) {
994
+ (this.rules as unknown as { parent?: Node }).parent = priorRulesParent;
995
+ }
996
+ const renderKey = ctx ? cloned._resolveRenderKey(ctx) : this.renderKey;
997
+ const selector = cloned.getSelector(renderKey);
998
+ if (selector instanceof Node) {
999
+ if (ctx || this !== this.sourceNode) {
1000
+ cloned.selector = selector.clone(false, undefined, ctx) as Selector | Nil;
1001
+ cloned.adopt(cloned.selector, ctx);
1002
+ }
1003
+ }
1004
+ const currentRules = this.getRules(renderKey);
1005
+ if (ctx && currentRules !== this.rules) {
1006
+ cloned.rules = currentRules;
1007
+ cloned.adopt(currentRules, ctx);
1008
+ }
1009
+ if (this !== this.sourceNode && cloned.rules === this.rules) {
1010
+ const rules = ctx ? cloned.enterRules(ctx) : cloned.rules;
1011
+ cloned.rules = rules.createShallowBodyWrapper(ctx);
1012
+ cloned.adopt(cloned.rules, ctx);
1013
+ }
1014
+ }
1015
+ if (!deep && ctx && this !== this.sourceNode && cloned.rules !== this.rules && cloned.rules.parent !== cloned) {
1016
+ cloned.adopt(cloned.rules, ctx);
1017
+ }
1018
+ return cloned;
1019
+ }
1020
+
1021
+ override copy(deep?: boolean): this {
1022
+ const node = super.copy(deep);
1023
+ const selectorSource = this.getOwnSelector() ?? this.selector;
1024
+ node.selector = selectorSource.sourceNode.copy(true) as Selector | Nil;
1025
+ node.adopt(node.selector);
1026
+ return node;
1027
+ }
1028
+
1029
+ override evalNode(context: Context): MaybePromise<Ruleset | Rules | Nil> {
1030
+ if (this.evaluated) {
1031
+ return this;
1032
+ }
1033
+ let pushedFrames = false;
1034
+ const renderKey = this._resolveRenderKey(context);
1035
+ const previousRenderKey = context.renderKey;
1036
+ if (renderKey !== undefined && renderKey !== CANONICAL) {
1037
+ context.renderKey = renderKey;
1038
+ }
1039
+ /** Should have been maybe cloned in preEval */
1040
+ this.evaluated = true;
1041
+ const collapseNesting = context.opts.collapseNesting;
1042
+
1043
+ // Store frames snapshot for collapseNesting serialization
1044
+ if (collapseNesting) {
1045
+ this.frames = [...context.frames];
1046
+ }
1047
+
1048
+ const out = pipe(
1049
+ () => {
1050
+ const selectorText = String(this.getSelector(renderKey)?.valueOf?.() ?? '');
1051
+ if (process.env.JESS_DEBUG_LOCK === 'throw-ruleset' && selectorText.includes('.call-inner-lock-mixin')) {
1052
+ throw new Error(`[lock-ruleset] ${JSON.stringify({
1053
+ selectorText,
1054
+ parent: this.parent?.type,
1055
+ sourceParent: this.sourceParent?.type,
1056
+ renderKey: String(renderKey),
1057
+ childCount: this.enterRules(context).get('value', context).length
1058
+ })}`);
1059
+ }
1060
+ if (
1061
+ selectorText.includes('.call-lock-mixin')
1062
+ || selectorText.includes('#guarded-caller')
1063
+ || selectorText.includes('#guarded-deeper')
1064
+ ) {
1065
+ }
1066
+ let guard = this.getGuard(renderKey);
1067
+ // Guard was already set to Nil (failed in a previous eval)
1068
+ if (guard instanceof Nil) {
1069
+ return guard;
1070
+ }
1071
+ // Evaluate guard at definition time (not call time like mixins)
1072
+ // This is different from mixins because rulesets can't use caller scope for guards
1073
+ if (guard) {
1074
+ return pipe(
1075
+ () => guard.eval(context),
1076
+ (guardResult) => {
1077
+ const selectorText = String(this.getSelector(renderKey)?.valueOf?.() ?? '');
1078
+ const guardPasses = Boolean(guardResult instanceof Bool && guardResult.value === true);
1079
+ if (selectorText.includes('#guarded') || selectorText.includes('#top') || selectorText.includes('#deeper')) {
1080
+ }
1081
+ if (!guardPasses) {
1082
+ // Guard failed - mark as Nil and return it
1083
+ this.guard = new Nil() as Condition | Nil;
1084
+ return new Nil();
1085
+ }
1086
+ // Guard passed - clear it and continue with selector evaluation
1087
+ this.guard = undefined as Condition | Nil | undefined;
1088
+ return undefined;
1089
+ }
1090
+ );
1091
+ }
1092
+ return undefined;
1093
+ },
1094
+ (guardResult) => {
1095
+ // If guard failed, return Nil (ruleset produces no output)
1096
+ if (guardResult instanceof Nil) {
1097
+ return guardResult;
1098
+ }
1099
+ let selector = this.getSelector(renderKey);
1100
+ const frame = atIndex(context.rulesetFrames, -1);
1101
+ if (frame && (this.hoistToRoot ?? context.opts.collapseNesting)) {
1102
+ this.hoistToRoot = true;
1103
+ }
1104
+
1105
+ if (selector instanceof Nil) {
1106
+ // If selector evaluates to Nil, return the rules body directly instead of the ruleset
1107
+ // This allows rules to be output even when there's no selector context
1108
+ // We don't push frames because there's no selector context
1109
+ // Store Nil in selector so next step can detect this case
1110
+ this.selector = selector as Selector | Nil;
1111
+ const evaluatedRules = this.enterRules(context).eval(context);
1112
+ // Update this.rules to point to evaluated Rules to prevent circular reference
1113
+ // when debug code traverses the AST
1114
+ if (isThenable(evaluatedRules)) {
1115
+ return (evaluatedRules as Promise<Rules>).then((rules) => {
1116
+ this._assignRules(rules, context);
1117
+ return rules;
1118
+ });
1119
+ }
1120
+ this._assignRules(evaluatedRules as Rules, context);
1121
+ return evaluatedRules;
1122
+ }
1123
+ // Preserve the sourceNode from the current selector before replacing it
1124
+ const preservedSourceNode = this._getSelectorSourceNode(this.getSelector(renderKey));
1125
+ this.selector = selector as Selector | Nil;
1126
+ this.adopt(this.selector, context);
1127
+ // Restore the sourceNode on the new selector so it's available when copying
1128
+ const currentSelector = this.getSelector(renderKey);
1129
+ if (preservedSourceNode && currentSelector) {
1130
+ {
1131
+ const selectorForSourceNode = currentSelector;
1132
+ if (selectorForSourceNode instanceof Node && preservedSourceNode) {
1133
+ selectorForSourceNode.sourceNode = preservedSourceNode;
1134
+ }
1135
+ }
1136
+ }
1137
+ if (context.opts.collapseNesting) {
1138
+ this.hoistToRoot = true;
1139
+ }
1140
+ context.rulesetFrames.push(this as Ruleset);
1141
+ context.frames.push(this);
1142
+ pushedFrames = true;
1143
+ return this.enterRules(context).eval(context);
1144
+ },
1145
+ (evaluatedRules: Rules | Nil) => {
1146
+ if (pushedFrames) {
1147
+ context.rulesetFrames.pop();
1148
+ context.frames.pop();
1149
+ }
1150
+ if (evaluatedRules instanceof Nil) {
1151
+ return evaluatedRules;
1152
+ }
1153
+
1154
+ // If selector was Nil, evaluatedRules is already Rules (not wrapped in Ruleset)
1155
+ // In that case, return it directly without wrapping back in Ruleset
1156
+ if (this.getSelector(renderKey) instanceof Nil) {
1157
+ // Selector was Nil, so we already returned Rules directly - just return it
1158
+ return evaluatedRules;
1159
+ }
1160
+
1161
+ this._assignRules(evaluatedRules as Rules, context);
1162
+ const rules = this.enterRules(context);
1163
+ if (rules.visibleRules(context).length === 0) {
1164
+ this._removeFlag(F_VISIBLE, context);
1165
+ }
1166
+ return this;
1167
+ }
1168
+ );
1169
+
1170
+ if (isThenable(out)) {
1171
+ return (out as Promise<Ruleset | Rules | Nil>).then(
1172
+ (result) => {
1173
+ context.renderKey = previousRenderKey;
1174
+ return result;
1175
+ },
1176
+ (error) => {
1177
+ context.renderKey = previousRenderKey;
1178
+ throw error;
1179
+ }
1180
+ );
1181
+ }
1182
+ context.renderKey = previousRenderKey;
1183
+ return out;
1184
+ }
1185
+
1186
+ /** @todo move to ToCssVisitor */
1187
+ // toCSS(context: Context, out: OutputCollector) {
1188
+ // const { sels, value } = this
1189
+ // context.inSelector = true
1190
+ // sels.toCSS(context, out)
1191
+ // context.inSelector = false
1192
+ // out.add(' ')
1193
+ // value.toCSS(context, out)
1194
+ // }
1195
+
1196
+ /** @todo Move to ToModuleVisitor */
1197
+ // toModule(context: Context, out: OutputCollector) {
1198
+ // out.add('$J.rule({\n', this.location)
1199
+ // context.indent++
1200
+ // const pre = context.pre
1201
+ // out.add(`${pre}sels: `)
1202
+ // this.sels.toModule(context, out)
1203
+ // out.add(`,\n${pre}value: `)
1204
+ // this.data.toModule(context, out)
1205
+ // context.indent--
1206
+ // out.add(`},${JSON.stringify(this.location)})`)
1207
+ // }
1208
+ }
1209
+
1210
+ type RulesetParams = ConstructorParameters<typeof Ruleset>;
1211
+
1212
+ export const ruleset = defineType<RulesetValue>(Ruleset, 'Ruleset') as (
1213
+ value: RulesetValue | RulesetParams[0],
1214
+ options?: RulesetParams[1],
1215
+ location?: RulesetParams[2],
1216
+ treeContext?: RulesetParams[3]
1217
+ ) => Ruleset;