@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,2139 @@
1
+ import type { Selector } from '../selector.js';
2
+ import type { Context } from '../../context.js';
3
+ import { SelectorList } from '../selector-list.js';
4
+ import { CompoundSelector } from '../selector-compound.js';
5
+ import { ComplexSelector } from '../selector-complex.js';
6
+ import type { ComplexSelectorValue } from '../selector-complex.js';
7
+ import { PseudoSelector } from '../selector-pseudo.js';
8
+ import { Combinator } from '../combinator.js';
9
+ import { isNode } from './is-node.js';
10
+ import { N } from '../node-type.js';
11
+ import { getImplicitSelector, getParentReplacementForAmpersand, wrapParentSelectorForNestedContext } from './selector-utils.js';
12
+ import { selectorMatch } from './selector-match-core.js';
13
+ import { Node } from '../node.js';
14
+ import { CANONICAL, EVAL, F_AMPERSAND } from '../node-base.js';
15
+ import { addParentEdge } from './cursor.js';
16
+
17
+ /**
18
+ * @todo Once extend correctness is stabilized and the remaining suites are
19
+ * green, do a dedicated performance review of this file. Focus on:
20
+ * - repeated nested `selectorMatch()` calls
21
+ * - unnecessary selector copying or wrapper allocation
22
+ * - opportunities to thread match metadata instead of recomputing it
23
+ */
24
+
25
+ /**
26
+ * Extend failure categories surfaced to callers while the rewrite remains
27
+ * intentionally incremental.
28
+ */
29
+ export type ExtendErrorType =
30
+ 'NOT_FOUND'
31
+ | 'ELEMENT_CONFLICT'
32
+ | 'ID_CONFLICT'
33
+ | 'AMPERSAND_BOUNDARY'
34
+ | 'PARTIAL_MATCH';
35
+
36
+ export const ExtendErrorType = {
37
+ NOT_FOUND: 'NOT_FOUND' as const,
38
+ ELEMENT_CONFLICT: 'ELEMENT_CONFLICT' as const,
39
+ ID_CONFLICT: 'ID_CONFLICT' as const,
40
+ AMPERSAND_BOUNDARY: 'AMPERSAND_BOUNDARY' as const,
41
+ PARTIAL_MATCH: 'PARTIAL_MATCH' as const
42
+ } as const;
43
+
44
+ /**
45
+ * Structured extend failure used instead of throwing during selector rewrites.
46
+ */
47
+ export class ExtendError extends Error {
48
+ constructor(
49
+ public type: ExtendErrorType,
50
+ message: string
51
+ ) {
52
+ super(message);
53
+ this.name = 'ExtendError';
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Result of trying to extend a selector.
59
+ *
60
+ * `value` is always returned so callers can keep using the original selector on
61
+ * misses without additional branching.
62
+ */
63
+ export interface ExtendResult {
64
+ value: Selector;
65
+ error?: ExtendError;
66
+ isChanged: boolean;
67
+ }
68
+
69
+ /** Creates a successful extend result around the mutated or rewritten selector. */
70
+ function createSuccessResult(value: Selector, isChanged = true): ExtendResult {
71
+ return { value, isChanged };
72
+ }
73
+
74
+ /** Creates a failed extend result while preserving the original selector. */
75
+ function createErrorResult(value: Selector, type: ExtendErrorType, message: string): ExtendResult {
76
+ return {
77
+ value,
78
+ error: new ExtendError(type, message),
79
+ isChanged: false
80
+ };
81
+ }
82
+
83
+ function expandGeneratedIsAlternatives(selector: Selector): Selector[] {
84
+ if (
85
+ isNode(selector, N.PseudoSelector)
86
+ && selector.generated === true
87
+ && selector.get('name') === ':is'
88
+ && getSelectorListArg(selector)
89
+ ) {
90
+ return [...getSelectorListArg(selector)!.get('value')];
91
+ }
92
+
93
+ return [selector];
94
+ }
95
+
96
+ function getDerivedSelectorRenderKey(source: Selector): symbol | number {
97
+ return source.renderKey === CANONICAL ? EVAL : source.renderKey;
98
+ }
99
+
100
+ function finalizeDerivedSelector<T extends Selector>(
101
+ source: Selector,
102
+ nextNode: T,
103
+ reusedChildren: readonly unknown[]
104
+ ): T {
105
+ const priorParents = reusedChildren.flatMap(child =>
106
+ child instanceof Node ? [[child, child.parent] as const] : []
107
+ );
108
+ nextNode.inherit(source);
109
+ nextNode.renderKey = getDerivedSelectorRenderKey(source);
110
+ for (const [child, priorParent] of priorParents) {
111
+ addParentEdge(child, nextNode.renderKey, nextNode);
112
+ Reflect.set(child, 'parent', priorParent);
113
+ }
114
+ return nextNode;
115
+ }
116
+
117
+ function createDerivedValueContainer(source: SelectorList, value: Selector[]): SelectorList;
118
+ function createDerivedValueContainer(source: ComplexSelector, value: ComplexSelectorValue): ComplexSelector;
119
+ function createDerivedValueContainer(source: CompoundSelector, value: Selector[]): CompoundSelector;
120
+ function createDerivedValueContainer(
121
+ source: SelectorList | ComplexSelector | CompoundSelector,
122
+ value: Selector[] | ComplexSelectorValue
123
+ ): SelectorList | ComplexSelector | CompoundSelector {
124
+ const nextNode = isNode(source, N.SelectorList)
125
+ ? new SelectorList(value, source.options ? { ...source.options } : undefined, source.location, source.treeContext)
126
+ : isNode(source, N.ComplexSelector)
127
+ ? new ComplexSelector(value, source.options ? { ...source.options } : undefined, source.location, source.treeContext)
128
+ : new CompoundSelector(value, source.options ? { ...source.options } : undefined, source.location, source.treeContext);
129
+ return finalizeDerivedSelector(source, nextNode, value);
130
+ }
131
+
132
+ function cloneComplexSelectorComponent(component: ComplexSelectorValue[number]): ComplexSelectorValue[number] {
133
+ const cloned: ComplexSelectorValue[number] = component instanceof Node
134
+ ? component.copy(true)
135
+ : component;
136
+ return cloned;
137
+ }
138
+
139
+ function createDerivedSelectorListFromSource(
140
+ source: Selector,
141
+ value: Selector[]
142
+ ): SelectorList {
143
+ const nextNode = new SelectorList(
144
+ value,
145
+ source.options ? { ...source.options } : undefined,
146
+ source.location,
147
+ source.treeContext
148
+ );
149
+ return finalizeDerivedSelector(source, nextNode, value);
150
+ }
151
+
152
+ function createDerivedPseudoWithArg(
153
+ source: PseudoSelector,
154
+ arg: Selector
155
+ ): PseudoSelector {
156
+ const nextNode = PseudoSelector.create(
157
+ { name: source.name, arg },
158
+ source.options ? { ...source.options } : undefined,
159
+ source.location,
160
+ source.treeContext
161
+ );
162
+ nextNode.generated = source.generated;
163
+ return finalizeDerivedSelector(source, nextNode, [arg]);
164
+ }
165
+
166
+ function getSelectorChildren(target: Selector): readonly Selector[] | undefined {
167
+ if (isNode(target, N.SelectorList | N.CompoundSelector | N.ComplexSelector)) {
168
+ return target.get('value');
169
+ }
170
+ return undefined;
171
+ }
172
+
173
+ function getSelectorArg(target: Selector): Selector | undefined {
174
+ if (!isNode(target, N.PseudoSelector)) {
175
+ return undefined;
176
+ }
177
+ const arg = target.get('arg');
178
+ return isNode(arg, N.Selector) ? arg : undefined;
179
+ }
180
+
181
+ function getSelectorListArg(target: Selector): SelectorList | undefined {
182
+ if (!isNode(target, N.PseudoSelector)) {
183
+ return undefined;
184
+ }
185
+ const arg = target.get('arg');
186
+ return isNode(arg, N.SelectorList) ? arg : undefined;
187
+ }
188
+
189
+ function getCompoundSelector(node: Selector): CompoundSelector | undefined {
190
+ return isNode(node, N.CompoundSelector) ? node : undefined;
191
+ }
192
+
193
+ function getComplexSelector(node: Selector): ComplexSelector | undefined {
194
+ return isNode(node, N.ComplexSelector) ? node : undefined;
195
+ }
196
+
197
+ function getSelectorList(node: Selector): SelectorList | undefined {
198
+ return isNode(node, N.SelectorList) ? node : undefined;
199
+ }
200
+
201
+ function normalizeSelectorListAlternatives(list: readonly Selector[]): Selector[] {
202
+ const flattened: Selector[] = [];
203
+ const seen = new Set<string>();
204
+
205
+ for (const item of list) {
206
+ const itemArgList = isNode(item, N.PseudoSelector) ? getSelectorListArg(item) : undefined;
207
+ if (isNode(item, N.PseudoSelector) && item.get('name') === ':is' && itemArgList) {
208
+ for (const child of itemArgList.get('value')) {
209
+ const key = child.valueOf();
210
+ if (!seen.has(key)) {
211
+ seen.add(key);
212
+ flattened.push(child);
213
+ }
214
+ }
215
+ continue;
216
+ }
217
+
218
+ const compound = getCompoundSelector(item);
219
+ if (compound && compound.get('value').length === 1) {
220
+ const only = compound.get('value')[0]!;
221
+ const onlyArgList = isNode(only, N.PseudoSelector) ? getSelectorListArg(only) : undefined;
222
+ if (isNode(only, N.PseudoSelector) && only.get('name') === ':is' && onlyArgList) {
223
+ for (const child of onlyArgList.get('value')) {
224
+ const key = child.valueOf();
225
+ if (!seen.has(key)) {
226
+ seen.add(key);
227
+ flattened.push(child);
228
+ }
229
+ }
230
+ continue;
231
+ }
232
+ }
233
+
234
+ const complex = getComplexSelector(item);
235
+ if (complex && complex.get('value').length === 1) {
236
+ const only = complex.get('value')[0]!;
237
+ const onlyArgList = isNode(only, N.PseudoSelector) ? getSelectorListArg(only) : undefined;
238
+ if (isNode(only, N.PseudoSelector) && only.get('name') === ':is' && onlyArgList) {
239
+ for (const child of onlyArgList.get('value')) {
240
+ const key = child.valueOf();
241
+ if (!seen.has(key)) {
242
+ seen.add(key);
243
+ flattened.push(child);
244
+ }
245
+ }
246
+ continue;
247
+ }
248
+ }
249
+
250
+ const key = item.valueOf();
251
+ if (seen.has(key)) {
252
+ continue;
253
+ }
254
+ seen.add(key);
255
+ flattened.push(item);
256
+ }
257
+ return flattened;
258
+ }
259
+
260
+ function canMutateSelectorContainer(target: Selector): boolean {
261
+ return target.renderKey !== CANONICAL || target.sourceNode !== target;
262
+ }
263
+
264
+ function setPseudoArg(target: PseudoSelector, arg: Selector): PseudoSelector {
265
+ if (!canMutateSelectorContainer(target)) {
266
+ return createDerivedPseudoWithArg(target, arg);
267
+ }
268
+ target.adopt(arg);
269
+ target.arg = arg;
270
+ target.invalidateCache();
271
+ return target;
272
+ }
273
+
274
+ function setSelectorContainerValue(
275
+ target: SelectorList | ComplexSelector | CompoundSelector,
276
+ value: Selector[]
277
+ ): SelectorList | ComplexSelector | CompoundSelector {
278
+ if (!canMutateSelectorContainer(target)) {
279
+ return createDerivedValueContainer(target, value);
280
+ }
281
+ Reflect.set(target, 'value', value);
282
+ for (const item of value) {
283
+ target.adopt(item);
284
+ }
285
+ target.invalidateCache();
286
+ return target;
287
+ }
288
+
289
+ function setSelectorContainerValueAt(
290
+ target: SelectorList | ComplexSelector | CompoundSelector,
291
+ index: number,
292
+ replacement: Selector
293
+ ): SelectorList | ComplexSelector | CompoundSelector {
294
+ const nextValue = target.get('value').slice();
295
+ nextValue[index] = replacement;
296
+ return setSelectorContainerValue(target, nextValue);
297
+ }
298
+
299
+ /**
300
+ * Appends a new alternative to an existing alternate container by returning
301
+ * a derived container that reuses unchanged child selectors.
302
+ *
303
+ * This is used for exact matches on selector lists and sole `:is(...)`
304
+ * containers, where the correct extend output is to add another alternative
305
+ * rather than wrap the whole selector again.
306
+ */
307
+ function appendAlternative(
308
+ target: Selector,
309
+ extendWith: Selector
310
+ ): Selector | undefined {
311
+ const next = expandGeneratedIsAlternatives(extendWith);
312
+
313
+ if (isNode(target, N.SelectorList)) {
314
+ const normalized = normalizeSelectorListAlternatives(target.get('value'));
315
+ const nextItems = normalizeSelectorListAlternatives([...normalized, ...next]);
316
+ return createDerivedValueContainer(target, nextItems);
317
+ }
318
+
319
+ if (isNode(target, N.PseudoSelector) && target.get('name') === ':is' && getSelectorArg(target)) {
320
+ const arg = getSelectorArg(target)!;
321
+ if (getSelectorList(arg)) {
322
+ const normalized = normalizeSelectorListAlternatives(arg.get('value'));
323
+ const nextItems = normalizeSelectorListAlternatives([...normalized, ...next]);
324
+ return createDerivedPseudoWithArg(target, createDerivedValueContainer(arg, nextItems));
325
+ }
326
+
327
+ const list = createDerivedSelectorListFromSource(arg, normalizeSelectorListAlternatives([arg, ...next]));
328
+ return createDerivedPseudoWithArg(target, list);
329
+ }
330
+
331
+ return undefined;
332
+ }
333
+
334
+ /**
335
+ * Produces the exact-extend output for one fully matched selector.
336
+ *
337
+ * When the matched selector already is an alternate container, the new
338
+ * selector is appended in place. Otherwise a selector list is created around
339
+ * the matched selector and the extension alternative.
340
+ *
341
+ * This is the preferred output for any selector that has an exact full match
342
+ * route, including full-match results discovered while running in partial
343
+ * mode. A generated
344
+ * `:is(...)` wrapper should only be introduced when the rewrite genuinely has
345
+ * to preserve unmatched siblings around a partial match.
346
+ */
347
+ function createAlternativeSelector(
348
+ target: Selector,
349
+ extendWith: Selector
350
+ ): Selector {
351
+ if (target.valueOf() === extendWith.valueOf()) {
352
+ return target;
353
+ }
354
+ const appended = appendAlternative(target, extendWith);
355
+ if (appended) {
356
+ return appended;
357
+ }
358
+
359
+ return createDerivedSelectorListFromSource(target, [target, ...expandGeneratedIsAlternatives(extendWith)]);
360
+ }
361
+
362
+ /**
363
+ * Wraps one matched selector fragment in a generated `:is(original, extendWith)`
364
+ * pseudo so partial extends can preserve unmatched siblings around it.
365
+ *
366
+ * When `selector` and `extendWith` are identical (e.g. `.class:extend(.class all)`),
367
+ * no wrapper is needed — the fragment is marked visible in place and returned as-is.
368
+ */
369
+ function wrapSelectorInIs(selector: Selector, extendWith: Selector): Selector {
370
+ // Flatten: if selector is already a generated :is(SelectorList), extract its items
371
+ // instead of nesting :is(:is(...), extension).
372
+ const selectorItems = expandGeneratedIsAlternatives(selector);
373
+ const extendItems = expandGeneratedIsAlternatives(extendWith);
374
+ const allItems = normalizeSelectorListAlternatives([...selectorItems, ...extendItems]);
375
+
376
+ if (allItems.length === 1) {
377
+ return selector;
378
+ }
379
+
380
+ const arg = SelectorList.create(allItems).inherit(selector);
381
+ arg.pre = undefined;
382
+ arg.post = undefined;
383
+
384
+ const wrapper = PseudoSelector.create({
385
+ name: ':is',
386
+ arg
387
+ });
388
+ wrapper.generated = true;
389
+ const inherited = wrapper.inherit(selector);
390
+ inherited.pre = undefined;
391
+ inherited.post = undefined;
392
+ return inherited;
393
+ }
394
+
395
+ /** Wraps a selector in a generated `:is(...)` without adding another alternate. */
396
+ function wrapSelectorAsGeneratedIs(selector: Selector): Selector {
397
+ const wrapper = PseudoSelector.create({
398
+ name: ':is',
399
+ arg: selector
400
+ });
401
+ wrapper.generated = true;
402
+ return wrapper.inherit(selector);
403
+ }
404
+
405
+ type CompoundConflictInfo = {
406
+ elements: Set<string>;
407
+ ids: Set<string>;
408
+ };
409
+
410
+ function createCompoundConflictInfo(): CompoundConflictInfo {
411
+ return {
412
+ elements: new Set<string>(),
413
+ ids: new Set<string>()
414
+ };
415
+ }
416
+
417
+ /**
418
+ * Collects the element and id selectors that can participate in one merged
419
+ * compound position.
420
+ *
421
+ * This mirrors extend's validity rule, not selector serialization. Complex
422
+ * selectors only contribute their terminal position because that is the part
423
+ * that can merge with the surrounding compound. Selector lists and `:is(...)`
424
+ * contribute the union of their alternatives.
425
+ */
426
+ function collectCompoundConflictInfo(
427
+ selector: Selector,
428
+ info: CompoundConflictInfo = createCompoundConflictInfo()
429
+ ): CompoundConflictInfo {
430
+ if (isNode(selector, N.BasicSelector)) {
431
+ if (selector.isTag) {
432
+ info.elements.add(selector.valueOf());
433
+ } else if (selector.isId) {
434
+ info.ids.add(selector.valueOf());
435
+ }
436
+ return info;
437
+ }
438
+
439
+ if (isNode(selector, N.CompoundSelector | N.SelectorList)) {
440
+ for (const child of selector.get('value')) {
441
+ collectCompoundConflictInfo(child, info);
442
+ }
443
+ return info;
444
+ }
445
+
446
+ if (isNode(selector, N.ComplexSelector)) {
447
+ const complexData = selector.get('value');
448
+ for (let i = complexData.length - 1; i >= 0; i--) {
449
+ const child = complexData[i]!;
450
+ if (isNode(child, N.Combinator)) {
451
+ continue;
452
+ }
453
+ collectCompoundConflictInfo(child, info);
454
+ break;
455
+ }
456
+ return info;
457
+ }
458
+
459
+ if (isNode(selector, N.PseudoSelector) && getSelectorArg(selector) && selector.get('name') === ':is') {
460
+ collectCompoundConflictInfo(getSelectorArg(selector)!, info);
461
+ }
462
+
463
+ return info;
464
+ }
465
+
466
+ /**
467
+ * Validates that inserting `extendWith` into the remaining members of one
468
+ * compound position would not create an impossible selector such as
469
+ * `span:is(div, .foo)` or `#first:is(#second, .foo)`.
470
+ */
471
+ function getCompoundConflictError(
472
+ surroundingMembers: readonly Selector[],
473
+ extendWith: Selector
474
+ ): ExtendError | undefined {
475
+ const surrounding = createCompoundConflictInfo();
476
+ for (const member of surroundingMembers) {
477
+ collectCompoundConflictInfo(member, surrounding);
478
+ }
479
+
480
+ const extension = collectCompoundConflictInfo(extendWith);
481
+ const surroundingElement = surrounding.elements.size > 0 ? [...surrounding.elements][0]! : undefined;
482
+ const conflictingElement = [...extension.elements].find(element => surroundingElement && element !== surroundingElement);
483
+ if (conflictingElement) {
484
+ return new ExtendError(ExtendErrorType.ELEMENT_CONFLICT, 'Extend would introduce a conflicting element selector');
485
+ }
486
+
487
+ const surroundingId = surrounding.ids.size > 0 ? [...surrounding.ids][0]! : undefined;
488
+ const conflictingId = [...extension.ids].find(id => surroundingId && id !== surroundingId);
489
+ if (conflictingId) {
490
+ return new ExtendError(ExtendErrorType.ID_CONFLICT, 'Extend would introduce a conflicting id selector');
491
+ }
492
+
493
+ return undefined;
494
+ }
495
+
496
+ /**
497
+ * Removes element and id selectors from `selector` when they are already
498
+ * supplied by the surrounding compound context outside the generated `:is(...)`
499
+ * wrapper.
500
+ *
501
+ * This keeps rewrites like `div:is(.a, div.b)` normalized to `div:is(.a, .b)`
502
+ * and `#foo:is(.class, #foo.other)` normalized to `#foo:is(.class, .other)`.
503
+ */
504
+ function stripRedundantCompoundContext(
505
+ selector: Selector,
506
+ surroundingMembers: readonly Selector[]
507
+ ): Selector {
508
+ const surrounding = createCompoundConflictInfo();
509
+ for (const member of surroundingMembers) {
510
+ collectCompoundConflictInfo(member, surrounding);
511
+ }
512
+
513
+ const normalize = (node: Selector): Selector | undefined => {
514
+ if (isNode(node, N.BasicSelector)) {
515
+ if (node.isTag && surrounding.elements.has(node.valueOf())) {
516
+ return undefined;
517
+ }
518
+ if (node.isId && surrounding.ids.has(node.valueOf())) {
519
+ return undefined;
520
+ }
521
+ return node;
522
+ }
523
+
524
+ const compound = getCompoundSelector(node);
525
+ if (compound) {
526
+ const next = compound.get('value')
527
+ .map(child => normalize(child))
528
+ .filter((child): child is Selector => !!child);
529
+ if (next.length === 0) {
530
+ return undefined;
531
+ }
532
+ if (next.length === 1) {
533
+ return next[0]!;
534
+ }
535
+ return CompoundSelector.create(next).inherit(node);
536
+ }
537
+
538
+ const list = getSelectorList(node);
539
+ if (list) {
540
+ const next = list.get('value')
541
+ .map(child => normalize(child))
542
+ .filter((child): child is Selector => !!child);
543
+ if (next.length === 0) {
544
+ return node;
545
+ }
546
+ if (next.length === 1) {
547
+ return next[0]!;
548
+ }
549
+ return SelectorList.create(next).inherit(node);
550
+ }
551
+
552
+ if (isNode(node, N.PseudoSelector) && node.get('name') === ':is' && getSelectorArg(node)) {
553
+ const nextArg = normalize(getSelectorArg(node)!);
554
+ if (!nextArg) {
555
+ return undefined;
556
+ }
557
+ const copy = node.copy(true);
558
+ return setPseudoArg(copy, nextArg);
559
+ }
560
+
561
+ return node;
562
+ };
563
+
564
+ return normalize(selector) ?? selector;
565
+ }
566
+
567
+ /**
568
+ * Rewrites a compound-local partial match by replacing only the consumed
569
+ * members with a generated `:is(...)` wrapper and leaving the unmatched
570
+ * remainder in place.
571
+ */
572
+ function wrapCompoundMatchRange(
573
+ targetCompound: CompoundSelector,
574
+ startIndex: number,
575
+ endIndex: number,
576
+ matchedIndices: number[] | undefined,
577
+ extendWith: Selector
578
+ ): Selector {
579
+ const effectiveMatchedIndices = matchedIndices && matchedIndices.length > 0
580
+ ? matchedIndices
581
+ : Array.from({ length: endIndex - startIndex + 1 }, (_, offset) => startIndex + offset);
582
+ const outsideMembers = getCompoundMembersOutsideRange(targetCompound, startIndex, endIndex, matchedIndices);
583
+ const matched = effectiveMatchedIndices.map(index => targetCompound.value[index]!);
584
+ const matchedSingle = matched.length === 1 ? matched[0]! : undefined;
585
+ const wrapped = wrapSelectorInIs(
586
+ matchedSingle ?? CompoundSelector.create(matched).inherit(targetCompound),
587
+ stripRedundantCompoundContext(extendWith, outsideMembers)
588
+ );
589
+ if (matchedSingle && wrapped === matchedSingle) {
590
+ return targetCompound;
591
+ }
592
+ const nextData: Selector[] = [];
593
+ const matchedIndexSet = new Set(effectiveMatchedIndices);
594
+
595
+ for (let i = 0; i < targetCompound.value.length; i++) {
596
+ const node = targetCompound.value[i]!;
597
+ if (i === effectiveMatchedIndices[0]) {
598
+ nextData.push(wrapped);
599
+ continue;
600
+ }
601
+ if (matchedIndexSet.has(i)) {
602
+ continue;
603
+ }
604
+ nextData.push(node);
605
+ }
606
+
607
+ if (nextData.length === 1) {
608
+ return nextData[0]!;
609
+ }
610
+
611
+ return ComplexSelector.create(nextData).inherit(targetCompound);
612
+ }
613
+
614
+ function getCompoundMembersOutsideRange(
615
+ compoundSelector: CompoundSelector,
616
+ startIndex: number,
617
+ endIndex: number,
618
+ matchedIndices: number[] | undefined
619
+ ): Selector[] {
620
+ const effectiveMatchedIndices = matchedIndices && matchedIndices.length > 0
621
+ ? matchedIndices
622
+ : Array.from({ length: endIndex - startIndex + 1 }, (_, offset) => startIndex + offset);
623
+ const matchedIndexSet = new Set(effectiveMatchedIndices);
624
+
625
+ return compoundSelector.value.filter((_, index) => !matchedIndexSet.has(index));
626
+ }
627
+
628
+ function wrapOrderedMatchRange(
629
+ targetSelector: ComplexSelector,
630
+ startIndex: number,
631
+ endIndex: number,
632
+ extendWith: Selector
633
+ ): Selector {
634
+ const matched = targetSelector.value.slice(startIndex, endIndex + 1);
635
+ const wrapped = wrapSelectorInIs(
636
+ matched.length === 1
637
+ ? matched[0]!
638
+ : ComplexSelector.create(matched).inherit(targetSelector),
639
+ extendWith
640
+ );
641
+ const nextData: Selector[] = [];
642
+
643
+ for (let i = 0; i < targetSelector.value.length; i++) {
644
+ const node = targetSelector.value[i]!;
645
+ if (i === startIndex) {
646
+ nextData.push(wrapped);
647
+ continue;
648
+ }
649
+ if (i > startIndex && i <= endIndex) {
650
+ continue;
651
+ }
652
+ nextData.push(node);
653
+ }
654
+
655
+ if (nextData.length === 1) {
656
+ return nextData[0]!;
657
+ }
658
+
659
+ return ComplexSelector.create(nextData).inherit(targetSelector);
660
+ }
661
+
662
+ /**
663
+ * Replaces one direct child selector inside its parent container.
664
+ *
665
+ * This keeps mutation localized to the owning parent so downstream caches and
666
+ * parent links stay consistent with the node model.
667
+ */
668
+ function replaceDirectSelectorChild(
669
+ parent: Selector,
670
+ child: Selector,
671
+ replacement: Selector
672
+ ): Selector | undefined {
673
+ const parentChildren = getSelectorChildren(parent);
674
+
675
+ if (
676
+ isNode(parent, N.PseudoSelector)
677
+ && (
678
+ parent.get('arg') === child
679
+ || (
680
+ getSelectorArg(parent) !== undefined
681
+ && getSelectorArg(parent)!.type === child.type
682
+ && getSelectorArg(parent)!.valueOf() === child.valueOf()
683
+ )
684
+ )
685
+ ) {
686
+ return setPseudoArg(parent, replacement);
687
+ }
688
+
689
+ if (parentChildren) {
690
+ const index = parentChildren.findIndex(node => node === child);
691
+ const fallbackIndex = index !== -1
692
+ ? index
693
+ : parentChildren.findIndex(node => node.type === child.type && node.valueOf() === child.valueOf());
694
+ if (fallbackIndex !== -1 && isNode(parent, N.SelectorList | N.ComplexSelector | N.CompoundSelector)) {
695
+ return setSelectorContainerValueAt(parent, fallbackIndex, replacement);
696
+ }
697
+ }
698
+
699
+ return undefined;
700
+ }
701
+
702
+ function getStructurallyMatchingDirectChildSelector(
703
+ target: Selector,
704
+ node: Selector
705
+ ): Selector | undefined {
706
+ const arg = getSelectorArg(target);
707
+ if (isNode(target, N.PseudoSelector) && arg) {
708
+ if (arg.type === node.type && arg.valueOf() === node.valueOf()) {
709
+ return arg;
710
+ }
711
+ return undefined;
712
+ }
713
+
714
+ const children = getSelectorChildren(target);
715
+ if (!children) {
716
+ return undefined;
717
+ }
718
+
719
+ return children.find(child => child.type === node.type && child.valueOf() === node.valueOf());
720
+ }
721
+
722
+ /**
723
+ * Resolves authored ampersands in a root complex selector against the provided
724
+ * parent without mutating the original target selector.
725
+ *
726
+ * This is currently used only for full-span crossed matches on the root target
727
+ * route.
728
+ */
729
+ function resolveAmpersandTarget(
730
+ target: ComplexSelector,
731
+ parent?: Selector
732
+ ): Selector | undefined {
733
+ const nextData: ComplexSelectorValue = [];
734
+ let replacedAny = false;
735
+
736
+ for (let i = 0; i < target.get('value').length; i++) {
737
+ const component = target.get('value')[i]!;
738
+ if (isNode(component, N.Ampersand)) {
739
+ const resolvedRaw = component.getResolvedSelector() ?? parent;
740
+ if (!resolvedRaw || isNode(resolvedRaw, N.Nil)) {
741
+ nextData.push(cloneComplexSelectorComponent(component));
742
+ continue;
743
+ }
744
+ nextData.push(...getParentReplacementForAmpersand(resolvedRaw, i === 0));
745
+ replacedAny = true;
746
+ continue;
747
+ }
748
+ nextData.push(cloneComplexSelectorComponent(component));
749
+ }
750
+
751
+ if (!replacedAny) {
752
+ return undefined;
753
+ }
754
+
755
+ return ComplexSelector.create(nextData).inherit(target);
756
+ }
757
+
758
+ /**
759
+ * Materializes the original matched target side when an extend crossed a parent
760
+ * boundary.
761
+ *
762
+ * Explicit authored ampersands resolve through their own replacement logic.
763
+ * Plain nested selectors with an implicit parent boundary are composed against
764
+ * `parent` on demand so the resulting selector is self-contained once hoisted
765
+ * or appended as an exact alternative.
766
+ */
767
+ function materializeCrossedTarget(
768
+ target: Selector,
769
+ parent: Selector | undefined
770
+ ): Selector | undefined {
771
+ const resolvedAmpersands = isNode(target, N.ComplexSelector)
772
+ ? resolveAmpersandTarget(target, parent)
773
+ : undefined;
774
+ if (resolvedAmpersands) {
775
+ return resolvedAmpersands;
776
+ }
777
+
778
+ if (!parent) {
779
+ return undefined;
780
+ }
781
+
782
+ // When both are SelectorLists, produce :is(parent) :is(inner) to avoid
783
+ // duplicating the parent prefix across every alternative.
784
+ if (isNode(target, N.SelectorList) && isNode(parent, N.SelectorList)) {
785
+ const parentFragment = wrapParentSelectorForNestedContext(parent, false);
786
+ const innerIs = PseudoSelector.create({ name: ':is', arg: target.copy(true) });
787
+ innerIs.generated = true;
788
+ return ComplexSelector.create([parentFragment, Combinator.create(' '), innerIs]).inherit(target);
789
+ }
790
+
791
+ return getImplicitSelector(target, parent, false);
792
+ }
793
+
794
+ /**
795
+ * Materializes authored ampersands throughout a hoisted selector so the
796
+ * returned selector no longer depends on external parent context.
797
+ *
798
+ * Once a rewrite hoists to root, every remaining `&` in the returned selector
799
+ * must be replaced with its parent selector using the same wrapping rules as
800
+ * ordinary ampersand replacement.
801
+ */
802
+ function materializeAmpersandsForHoist(
803
+ selector: Selector,
804
+ parent: Selector
805
+ ): Selector {
806
+ if (isNode(selector, N.Ampersand)) {
807
+ const resolved = selector.getResolvedSelector() ?? parent;
808
+ const resolvedCopy = resolved.copy(true);
809
+ return materializeAmpersandsForHoist(resolvedCopy, parent);
810
+ }
811
+
812
+ const selectorList = getSelectorList(selector);
813
+ if (selectorList) {
814
+ const next = selectorList.get('value').map(child =>
815
+ materializeAmpersandsForHoist(child.copy(true), parent)
816
+ );
817
+ const rebuilt = SelectorList.create(next).inherit(selector);
818
+ rebuilt.hoistToRoot = selector.hoistToRoot;
819
+ return rebuilt;
820
+ }
821
+
822
+ const complex = getComplexSelector(selector);
823
+ if (complex) {
824
+ const nextData: Selector[] = [];
825
+
826
+ for (let i = 0; i < complex.get('value').length; i++) {
827
+ const child = complex.get('value')[i]!;
828
+ if (isNode(child, N.Ampersand)) {
829
+ const resolved = child.getResolvedSelector() ?? parent;
830
+ const replacement = materializeAmpersandsForHoist(resolved.copy(true), parent);
831
+ nextData.push(...getParentReplacementForAmpersand(replacement, i === 0));
832
+ continue;
833
+ }
834
+
835
+ nextData.push(materializeAmpersandsForHoist(child.copy(true), parent));
836
+ }
837
+
838
+ const rebuilt = ComplexSelector.create(nextData).inherit(selector);
839
+ rebuilt.hoistToRoot = selector.hoistToRoot;
840
+ return rebuilt;
841
+ }
842
+
843
+ const compound = getCompoundSelector(selector);
844
+ if (compound) {
845
+ const nextData: Selector[] = [];
846
+
847
+ for (const selectorChild of compound.get('value')) {
848
+ if (isNode(selectorChild, N.Ampersand)) {
849
+ const resolved = materializeAmpersandsForHoist((selectorChild.getResolvedSelector() ?? parent)!.copy(true), parent);
850
+ if (isNode(resolved, N.CompoundSelector)) {
851
+ nextData.push(...resolved.get('value'));
852
+ } else if (isNode(resolved, N.ComplexSelector | N.SelectorList)) {
853
+ nextData.push(wrapSelectorAsGeneratedIs(resolved));
854
+ } else {
855
+ nextData.push(resolved);
856
+ }
857
+ continue;
858
+ }
859
+
860
+ nextData.push(materializeAmpersandsForHoist(selectorChild.copy(true), parent));
861
+ }
862
+
863
+ if (nextData.length === 1) {
864
+ const only = nextData[0]!;
865
+ only.hoistToRoot = selector.hoistToRoot;
866
+ return only;
867
+ }
868
+
869
+ const rebuilt = CompoundSelector.create(nextData).inherit(selector);
870
+ rebuilt.hoistToRoot = selector.hoistToRoot;
871
+ return rebuilt;
872
+ }
873
+
874
+ if (isNode(selector, N.PseudoSelector) && isNode(selector.get('arg'), N.Selector)) {
875
+ const copy = selector.copy(true);
876
+ const nextCopy = setPseudoArg(copy, materializeAmpersandsForHoist(getSelectorArg(selector)!, parent));
877
+ nextCopy.hoistToRoot = selector.hoistToRoot;
878
+ return nextCopy;
879
+ }
880
+
881
+ const copy = selector.copy(true);
882
+ copy.hoistToRoot = selector.hoistToRoot;
883
+ return copy;
884
+ }
885
+
886
+ function getCrossedAmpersandParent(location: ReturnType<typeof selectorMatch>['matches'][number]): Selector | undefined {
887
+ const crossing = location.ampersandCrossings?.find(crossing => crossing.parentSegment && isNode(crossing.parentSegment.containingNode, N.Selector));
888
+ return crossing?.parentSegment?.containingNode;
889
+ }
890
+
891
+ /**
892
+ * Rewrites a root compound span that crossed an ampersand by resolving the
893
+ * matched span against the parent seam and leaving unmatched compound members
894
+ * outside the generated `:is(...)`.
895
+ */
896
+ function wrapResolvedCompoundSpan(
897
+ targetCompound: CompoundSelector,
898
+ startIndex: number,
899
+ endIndex: number,
900
+ extendWith: Selector,
901
+ resolvedParent: Selector
902
+ ): Selector {
903
+ const matchedMembers = targetCompound.value.slice(startIndex, endIndex + 1);
904
+ const matchedSelector = matchedMembers.length === 1
905
+ ? matchedMembers[0]!
906
+ : CompoundSelector.create(matchedMembers).inherit(targetCompound);
907
+ const outsideMembers = targetCompound.value.filter((_: Selector, index: number) => index < startIndex || index > endIndex);
908
+ const wrapped = wrapSelectorInIs(
909
+ materializeAmpersandsForHoist(matchedSelector, resolvedParent),
910
+ stripRedundantCompoundContext(extendWith, outsideMembers)
911
+ );
912
+ const nextData: Selector[] = [];
913
+
914
+ for (let i = 0; i < targetCompound.value.length; i++) {
915
+ if (i === startIndex) {
916
+ nextData.push(wrapped);
917
+ continue;
918
+ }
919
+ if (i > startIndex && i <= endIndex) {
920
+ continue;
921
+ }
922
+ nextData.push(targetCompound.value[i]!);
923
+ }
924
+
925
+ if (nextData.length === 1) {
926
+ return nextData[0]!;
927
+ }
928
+
929
+ return ComplexSelector.create(nextData).inherit(targetCompound);
930
+ }
931
+
932
+ function getLastOrderedSelector(selector: Selector): Selector {
933
+ const complex = getComplexSelector(selector);
934
+ if (complex) {
935
+ for (let i = complex.get('value').length - 1; i >= 0; i--) {
936
+ const child = complex.get('value')[i]!;
937
+ if (!isNode(child, N.Combinator)) {
938
+ return child;
939
+ }
940
+ }
941
+ }
942
+
943
+ return selector;
944
+ }
945
+
946
+ function buildMatchedCompoundSelector(
947
+ targetCompound: CompoundSelector,
948
+ startIndex: number,
949
+ endIndex: number,
950
+ matchedIndices?: number[]
951
+ ): Selector {
952
+ const effectiveMatchedIndices = matchedIndices && matchedIndices.length > 0
953
+ ? matchedIndices
954
+ : Array.from({ length: endIndex - startIndex + 1 }, (_, offset) => startIndex + offset);
955
+ const matched = effectiveMatchedIndices.map(index => targetCompound.value[index]!);
956
+
957
+ if (matched.length === 1) {
958
+ return matched[0]!;
959
+ }
960
+
961
+ return CompoundSelector.create(matched).inherit(targetCompound);
962
+ }
963
+
964
+ /**
965
+ * Rewrites a crossed ordered span whose terminal position is a compound with
966
+ * unmatched tail members that must stay outside the generated `:is(...)`.
967
+ *
968
+ * When the terminal compound crossed an ampersand seam, the matched portion is
969
+ * the full crossed target segment, not just the visible `matchedIndices`.
970
+ * Otherwise the authored `&` would leak into the remainder instead of staying
971
+ * attached to the matched fragment it helped complete.
972
+ */
973
+ function wrapResolvedOrderedSpanWithTailRemainder(
974
+ targetSelector: ComplexSelector,
975
+ startIndex: number,
976
+ endIndex: number,
977
+ extendWith: Selector,
978
+ resolvedParent: Selector,
979
+ terminalFind: Selector,
980
+ location?: ReturnType<typeof selectorMatch>['matches'][number],
981
+ context?: Context
982
+ ): Selector | undefined {
983
+ const tail = targetSelector.value[endIndex]!;
984
+ if (!isNode(tail, N.CompoundSelector)) {
985
+ return undefined;
986
+ }
987
+
988
+ const tailMatch = selectorMatch(terminalFind, tail, resolvedParent, context);
989
+ const tailLocation = tailMatch.matches.find(match => match.containingNode === tail);
990
+ if (!tailLocation || tailLocation.startIndex === undefined || tailLocation.endIndex === undefined) {
991
+ return undefined;
992
+ }
993
+ const crossedTailSegment = location?.ampersandCrossings?.find(crossing =>
994
+ crossing.targetSegment.containingNode === tail
995
+ )?.targetSegment ?? tailLocation.ampersandCrossings?.find(crossing =>
996
+ crossing.targetSegment.containingNode === tail
997
+ )?.targetSegment;
998
+ const tailStartIndex = crossedTailSegment?.startIndex ?? tailLocation.startIndex;
999
+ const tailEndIndex = crossedTailSegment?.endIndex ?? tailLocation.endIndex;
1000
+ const tailMatchedIndices = crossedTailSegment?.matchedIndices ?? tailLocation.matchedIndices;
1001
+ const effectiveTailMatchedIndices = crossedTailSegment ? undefined : tailMatchedIndices;
1002
+
1003
+ const matchedPrefix: Selector[] = [];
1004
+ for (let i = startIndex; i < endIndex; i++) {
1005
+ matchedPrefix.push(materializeAmpersandsForHoist(targetSelector.value[i]!.copy(true), resolvedParent));
1006
+ }
1007
+
1008
+ const matchedTailSelector = buildMatchedCompoundSelector(
1009
+ tail,
1010
+ tailStartIndex,
1011
+ tailEndIndex,
1012
+ effectiveTailMatchedIndices
1013
+ );
1014
+ matchedPrefix.push(crossedTailSegment
1015
+ ? materializeAmpersandsForHoist(matchedTailSelector, resolvedParent)
1016
+ : matchedTailSelector);
1017
+
1018
+ const orderedMatchedSelector = matchedPrefix.length === 1
1019
+ ? matchedPrefix[0]!
1020
+ : ComplexSelector.create(matchedPrefix).inherit(targetSelector);
1021
+ const wrapped = wrapSelectorInIs(orderedMatchedSelector, extendWith);
1022
+ const tailRemainder = getCompoundMembersOutsideRange(
1023
+ tail,
1024
+ tailStartIndex,
1025
+ tailEndIndex,
1026
+ effectiveTailMatchedIndices
1027
+ );
1028
+ const inserted = tailRemainder.length > 0
1029
+ ? CompoundSelector.create([wrapped, ...tailRemainder]).inherit(tail)
1030
+ : wrapped;
1031
+
1032
+ const nextData: Selector[] = [];
1033
+ for (let i = 0; i < targetSelector.value.length; i++) {
1034
+ if (i === startIndex) {
1035
+ nextData.push(inserted);
1036
+ continue;
1037
+ }
1038
+ if (i > startIndex && i <= endIndex) {
1039
+ continue;
1040
+ }
1041
+ nextData.push(targetSelector.value[i]!);
1042
+ }
1043
+
1044
+ if (nextData.length === 1) {
1045
+ return nextData[0]!;
1046
+ }
1047
+
1048
+ return ComplexSelector.create(nextData).inherit(targetSelector);
1049
+ }
1050
+
1051
+ /**
1052
+ * Rewrites one direct child selector of `target` by delegating to
1053
+ * `tryExtendSelector()` on that child and then replacing it through the parent
1054
+ * container.
1055
+ *
1056
+ * This is a structural rewrite step on an already-selected subtree. When that
1057
+ * child still belongs to the same authored selector route, the same `parent`
1058
+ * context is forwarded so authored ampersands inside the child keep the same
1059
+ * resolution context the outer target matched with.
1060
+ *
1061
+ * The fallback `selectorMatch()` call is only used to recover crossed-seam
1062
+ * hoist information for exact child rewrites that do not otherwise surface it
1063
+ * on the rewritten child node itself.
1064
+ */
1065
+ function tryExtendDirectChildSelector(
1066
+ target: Selector,
1067
+ child: Selector | undefined,
1068
+ find: Selector,
1069
+ extendWith: Selector,
1070
+ parent?: Selector,
1071
+ crossedAmpersandHint = false,
1072
+ context?: Context
1073
+ ): ExtendResult | undefined {
1074
+ if (!child) {
1075
+ return undefined;
1076
+ }
1077
+
1078
+ const nested = tryExtendSelector(child, find, extendWith, true, parent, context);
1079
+ if (nested.error) {
1080
+ return undefined;
1081
+ }
1082
+
1083
+ const nextTarget = replaceDirectSelectorChild(target, child, nested.value);
1084
+ if (!nextTarget) {
1085
+ return undefined;
1086
+ }
1087
+
1088
+ if (nested.value.hoistToRoot || crossedAmpersandHint) {
1089
+ nextTarget.hoistToRoot = true;
1090
+ } else if (parent && child.hasFlag(F_AMPERSAND)) {
1091
+ const childMatch = selectorMatch(find, child, parent, context);
1092
+ if (childMatch.fullMatch && childMatch.crossesAmpersand) {
1093
+ nextTarget.hoistToRoot = true;
1094
+ }
1095
+ }
1096
+ return createSuccessResult(nextTarget, nested.isChanged);
1097
+ }
1098
+
1099
+ /**
1100
+ * Finds the direct child selector of `target` that structurally owns `node`.
1101
+ *
1102
+ * This lets partial rewrites recurse into the nearest direct child selector
1103
+ * even when the selected match location lives several wrapper levels below it.
1104
+ */
1105
+ function getContainingDirectChildSelector(
1106
+ target: Selector,
1107
+ node: Node
1108
+ ): Selector | undefined {
1109
+ if (!isNode(target, N.SelectorList | N.CompoundSelector | N.ComplexSelector)) {
1110
+ return undefined;
1111
+ }
1112
+
1113
+ let current: Node | undefined = node;
1114
+ while (current && current.parent && current.parent !== target) {
1115
+ current = current.parent;
1116
+ }
1117
+
1118
+ if (current && current.parent === target && isNode(current, N.Selector)) {
1119
+ return current;
1120
+ }
1121
+
1122
+ return undefined;
1123
+ }
1124
+
1125
+ /**
1126
+ * Returns the single direct child selector selected by one exact location on
1127
+ * an ordered or alternate container, when that location maps to exactly one
1128
+ * child slot of the current target.
1129
+ */
1130
+ function getSingleMatchedDirectChild(
1131
+ target: Selector,
1132
+ location: ReturnType<typeof selectorMatch>['matches'][number]
1133
+ ): Selector | undefined {
1134
+ if (
1135
+ !isNode(target, N.SelectorList | N.CompoundSelector | N.ComplexSelector)
1136
+ || location.containingNode !== target
1137
+ || location.startIndex === undefined
1138
+ || location.startIndex !== location.endIndex
1139
+ ) {
1140
+ return undefined;
1141
+ }
1142
+
1143
+ const children = getSelectorChildren(target);
1144
+ return children ? children[location.startIndex] : undefined;
1145
+ }
1146
+
1147
+ /** Returns the direct selector-valued arg on a pseudo selector, if any. */
1148
+ function getDirectPseudoArg(
1149
+ target: Selector
1150
+ ): Selector | undefined {
1151
+ return isNode(target, N.PseudoSelector) && getSelectorArg(target)
1152
+ ? getSelectorArg(target)
1153
+ : undefined;
1154
+ }
1155
+
1156
+ /** Returns the direct selector-valued arg on a `:is(...)` pseudo, if any. */
1157
+ function getDirectIsArg(
1158
+ target: Selector
1159
+ ): Selector | undefined {
1160
+ return isNode(target, N.PseudoSelector) && target.get('name') === ':is' && getSelectorArg(target)
1161
+ ? getSelectorArg(target)
1162
+ : undefined;
1163
+ }
1164
+
1165
+ /** Returns the directly rewriteable selector-list container on `target`, if any. */
1166
+ function getDirectSelectorList(
1167
+ target: Selector
1168
+ ): Selector | undefined {
1169
+ return getSelectorList(target) ?? getSelectorListArg(target);
1170
+ }
1171
+
1172
+ /**
1173
+ * Appends to the direct selector-list container that already owns the matched
1174
+ * selector, preserving surrounding wrapper shape.
1175
+ */
1176
+ function tryAppendToContainingSelectorList(
1177
+ target: Selector,
1178
+ containingNode: Selector,
1179
+ extendWith: Selector
1180
+ ): ExtendResult | undefined {
1181
+ const list = getDirectSelectorList(target);
1182
+ if (!list) {
1183
+ return undefined;
1184
+ }
1185
+ if (containingNode.parent !== list) {
1186
+ return undefined;
1187
+ }
1188
+
1189
+ const replacement = appendAlternative(list, extendWith);
1190
+ if (!replacement) {
1191
+ return undefined;
1192
+ }
1193
+ if (list === target) {
1194
+ return createSuccessResult(replacement);
1195
+ }
1196
+ const nextTarget = replaceDirectSelectorChild(target, list, replacement);
1197
+ if (!nextTarget) {
1198
+ return undefined;
1199
+ }
1200
+ return createSuccessResult(nextTarget);
1201
+ }
1202
+
1203
+ /**
1204
+ * Appends at the end of the direct selector-list container when `find`
1205
+ * fully matches that container under the same parent context.
1206
+ */
1207
+ function tryAppendToDirectSelectorListOnFullMatch(
1208
+ target: Selector,
1209
+ find: Selector,
1210
+ extendWith: Selector,
1211
+ parent?: Selector,
1212
+ context?: Context
1213
+ ): ExtendResult | undefined {
1214
+ const list = getDirectSelectorList(target);
1215
+ if (!list) {
1216
+ return undefined;
1217
+ }
1218
+ const innerMatch = selectorMatch(find, list, parent, context);
1219
+ if (!innerMatch.fullMatch) {
1220
+ return undefined;
1221
+ }
1222
+
1223
+ const replacement = appendAlternative(list, extendWith);
1224
+ if (!replacement) {
1225
+ return undefined;
1226
+ }
1227
+ if (list === target) {
1228
+ if (innerMatch.crossesAmpersand) {
1229
+ replacement.hoistToRoot = true;
1230
+ }
1231
+ return createSuccessResult(replacement);
1232
+ }
1233
+ const nextTarget = replaceDirectSelectorChild(target, list, replacement);
1234
+ if (!nextTarget) {
1235
+ return undefined;
1236
+ }
1237
+ if (innerMatch.crossesAmpersand) {
1238
+ nextTarget.hoistToRoot = true;
1239
+ }
1240
+ return createSuccessResult(nextTarget);
1241
+ }
1242
+
1243
+ function getLastOrderedSelectorIndex(selector: ComplexSelector): number {
1244
+ for (let i = selector.value.length - 1; i >= 0; i--) {
1245
+ if (!isNode(selector.value[i], N.Combinator)) {
1246
+ return i;
1247
+ }
1248
+ }
1249
+ return -1;
1250
+ }
1251
+
1252
+ function mergeCompoundMembersIntoSelector(
1253
+ members: readonly Selector[],
1254
+ selector: Selector
1255
+ ): Selector {
1256
+ const merged: Selector[] = [...members];
1257
+ const compound = getCompoundSelector(selector);
1258
+ if (compound) {
1259
+ merged.push(...compound.get('value'));
1260
+ } else {
1261
+ merged.push(selector);
1262
+ }
1263
+ if (merged.length === 1) {
1264
+ return merged[0]!;
1265
+ }
1266
+ return CompoundSelector.create(merged).inherit(selector);
1267
+ }
1268
+
1269
+ /**
1270
+ * Appends `extendWith` into a nested `:is(...)` when `find` already fully
1271
+ * matches a selector that belongs to the same rewritten component.
1272
+ *
1273
+ * The important distinction here is component identity, not the mere presence
1274
+ * of `:is(...)`: when the full match stays attached to the same selector
1275
+ * component, the rewrite should append into that component's alternate
1276
+ * container instead of widening the outer selector shape. Parent-aware crossed
1277
+ * full matches hoist the owning target so the returned selector is later
1278
+ * materialized against that parent context.
1279
+ */
1280
+ function tryAppendIntoNestedIsOnFullMatch(
1281
+ target: Selector,
1282
+ find: Selector,
1283
+ extendWith: Selector,
1284
+ parent?: Selector,
1285
+ context?: Context
1286
+ ): ExtendResult | undefined {
1287
+ if (!isNode(target, N.CompoundSelector | N.ComplexSelector)) {
1288
+ return undefined;
1289
+ }
1290
+
1291
+ const targetData = getSelectorChildren(target);
1292
+ if (!targetData) {
1293
+ return undefined;
1294
+ }
1295
+ for (let i = 0; i < targetData.length; i++) {
1296
+ const child = targetData[i];
1297
+ const childArg = getSelectorArg(child);
1298
+ if (!(isNode(child, N.PseudoSelector) && child.get('name') === ':is' && childArg)) {
1299
+ continue;
1300
+ }
1301
+ const innerMatch = selectorMatch(find, childArg, parent, context);
1302
+ if (!innerMatch.fullMatch) {
1303
+ continue;
1304
+ }
1305
+ const replacement = appendAlternative(child, extendWith);
1306
+ if (!replacement) {
1307
+ continue;
1308
+ }
1309
+ const nextTarget = replaceDirectSelectorChild(target, child, replacement);
1310
+ if (!nextTarget) {
1311
+ continue;
1312
+ }
1313
+ if (innerMatch.crossesAmpersand) {
1314
+ nextTarget.hoistToRoot = true;
1315
+ }
1316
+ return createSuccessResult(nextTarget);
1317
+ }
1318
+
1319
+ return undefined;
1320
+ }
1321
+
1322
+ /**
1323
+ * Pulls matched compound members into the terminal selector of a nested
1324
+ * complex branch when those members all refer to the same selector component.
1325
+ *
1326
+ * This is the case where outer compound members and the branch terminal are
1327
+ * interchangeable because they all describe the same element/component. In
1328
+ * that situation the rewrite should stay attached to that component rather
1329
+ * than widen across the entire outer compound span.
1330
+ */
1331
+ function tryPullCompoundMatchIntoNestedIsBranch(
1332
+ target: CompoundSelector,
1333
+ location: ReturnType<typeof selectorMatch>['matches'][number],
1334
+ find: Selector,
1335
+ extendWith: Selector,
1336
+ context?: Context
1337
+ ): ExtendResult | undefined {
1338
+ if (!(location.startIndex !== undefined && location.endIndex !== undefined)) {
1339
+ return undefined;
1340
+ }
1341
+
1342
+ const targetValues = target.get('value');
1343
+ const pseudoIndex = targetValues.findIndex((node, index) =>
1344
+ index >= location.startIndex!
1345
+ && index <= location.endIndex!
1346
+ && isNode(node, N.PseudoSelector)
1347
+ && node.get('name') === ':is'
1348
+ && getSelectorArg(node)
1349
+ );
1350
+ if (pseudoIndex === -1) {
1351
+ return undefined;
1352
+ }
1353
+
1354
+ const pseudoNode = targetValues[pseudoIndex];
1355
+ if (!isNode(pseudoNode, N.PseudoSelector)) {
1356
+ return undefined;
1357
+ }
1358
+ const pulledMembers = targetValues.filter((node, index) =>
1359
+ index >= location.startIndex!
1360
+ && index <= location.endIndex!
1361
+ && index !== pseudoIndex
1362
+ );
1363
+ if (pulledMembers.length === 0) {
1364
+ return undefined;
1365
+ }
1366
+
1367
+ const arg = getSelectorArg(pseudoNode) ?? pseudoNode.get('arg');
1368
+ if (!isNode(arg, N.Selector)) {
1369
+ return undefined;
1370
+ }
1371
+ const alternatives = isNode(arg, N.SelectorList)
1372
+ ? [...arg.get('value')]
1373
+ : [arg];
1374
+
1375
+ for (let i = 0; i < alternatives.length; i++) {
1376
+ const alternative = alternatives[i]!;
1377
+ if (!isNode(alternative, N.ComplexSelector)) {
1378
+ continue;
1379
+ }
1380
+ const lastIndex = getLastOrderedSelectorIndex(alternative);
1381
+ if (lastIndex === -1) {
1382
+ continue;
1383
+ }
1384
+
1385
+ const lastSelector = alternative.get('value')[lastIndex]!;
1386
+ const merged = mergeCompoundMembersIntoSelector(pulledMembers, lastSelector);
1387
+ const mergedMatch = selectorMatch(find, merged, undefined, context);
1388
+ if (!mergedMatch.fullMatch) {
1389
+ continue;
1390
+ }
1391
+
1392
+ const wrapped = wrapSelectorInIs(merged, extendWith);
1393
+ const nextAlternative = setSelectorContainerValueAt(
1394
+ alternative,
1395
+ lastIndex,
1396
+ wrapped
1397
+ );
1398
+ const nextArg = isNode(arg, N.SelectorList)
1399
+ ? setSelectorContainerValueAt(arg, i, nextAlternative)
1400
+ : nextAlternative;
1401
+ const nextPseudo = setPseudoArg(pseudoNode, nextArg);
1402
+
1403
+ const nextData = targetValues
1404
+ .flatMap((node, index) => {
1405
+ if (index < location.startIndex! || index > location.endIndex! || index === pseudoIndex) {
1406
+ return [index === pseudoIndex ? nextPseudo : node];
1407
+ }
1408
+ return [];
1409
+ });
1410
+ const nextTarget = setSelectorContainerValue(target, nextData);
1411
+ return createSuccessResult(nextTarget);
1412
+ }
1413
+
1414
+ return undefined;
1415
+ }
1416
+
1417
+ /** Picks the most useful rewrite location from a selector-match result. */
1418
+ function getPreferredMatchLocation(
1419
+ target: Selector,
1420
+ match: ReturnType<typeof selectorMatch>
1421
+ ): ReturnType<typeof selectorMatch>['matches'][number] {
1422
+ return match.matches.find(location => location.exact && location.containingNode === target)
1423
+ ?? match.matches.find(location => location.exact)
1424
+ ?? match.matches[0]!;
1425
+ }
1426
+
1427
+ /**
1428
+ * Produces the exact-mode extend output once a full match has already been
1429
+ * established by `selectorMatch()`.
1430
+ */
1431
+ function createExactExtendResult(
1432
+ target: Selector,
1433
+ extendWith: Selector,
1434
+ parent: Selector | undefined,
1435
+ crossedAmpersand: boolean,
1436
+ finalize: (result: ExtendResult) => ExtendResult
1437
+ ): ExtendResult {
1438
+ if (
1439
+ isNode(target, N.SelectorList)
1440
+ || (isNode(target, N.PseudoSelector) && target.get('name') === ':is' && isNode(target.get('arg'), N.Selector))
1441
+ ) {
1442
+ // When the match crossed a parent boundary, materialize before appending.
1443
+ if (crossedAmpersand) {
1444
+ const resolved = materializeCrossedTarget(target, parent);
1445
+ if (resolved) {
1446
+ return finalize(createSuccessResult(createAlternativeSelector(resolved, extendWith)));
1447
+ }
1448
+ }
1449
+ return finalize(createSuccessResult(createAlternativeSelector(target, extendWith)));
1450
+ }
1451
+
1452
+ const resolved = crossedAmpersand
1453
+ ? materializeCrossedTarget(target, parent)
1454
+ : resolveAmpersandTarget(target, parent);
1455
+ if (resolved) {
1456
+ return finalize(createSuccessResult(createAlternativeSelector(resolved, extendWith)));
1457
+ }
1458
+
1459
+ return finalize(createSuccessResult(createAlternativeSelector(target, extendWith)));
1460
+ }
1461
+
1462
+ /**
1463
+ * Handles the fallback path where the top-level target had no partial matches,
1464
+ * but an exact nested append or direct child rewrite may still be valid.
1465
+ */
1466
+ function tryHandleNoPartialMatch(
1467
+ target: Selector,
1468
+ find: Selector,
1469
+ extendWith: Selector,
1470
+ parent: Selector | undefined,
1471
+ finalize: (result: ExtendResult) => ExtendResult,
1472
+ context?: Context
1473
+ ): ExtendResult | undefined {
1474
+ const nestedIsAppend = tryAppendIntoNestedIsOnFullMatch(target, find, extendWith, parent, context);
1475
+ if (nestedIsAppend) {
1476
+ return finalize(nestedIsAppend);
1477
+ }
1478
+
1479
+ const nestedDirectChild = getDirectPseudoArg(target)
1480
+ ? tryExtendDirectChildSelector(target, getDirectPseudoArg(target), find, extendWith, parent, false, context)
1481
+ : undefined;
1482
+ if (nestedDirectChild) {
1483
+ if (nestedDirectChild.value.hoistToRoot) {
1484
+ target.hoistToRoot = true;
1485
+ }
1486
+ return finalize(nestedDirectChild);
1487
+ }
1488
+
1489
+ return undefined;
1490
+ }
1491
+
1492
+ function tryHandleMultiDirectChildFullMatches(
1493
+ target: Selector,
1494
+ find: Selector,
1495
+ extendWith: Selector,
1496
+ parent: Selector | undefined,
1497
+ finalize: (result: ExtendResult) => ExtendResult,
1498
+ context?: Context
1499
+ ): ExtendResult | undefined {
1500
+ if (!isNode(target, N.SelectorList | N.CompoundSelector | N.ComplexSelector)) {
1501
+ return undefined;
1502
+ }
1503
+
1504
+ const matchedChildren: Array<{ index: number; child: Selector }> = [];
1505
+ const targetData = getSelectorChildren(target);
1506
+ if (!targetData) {
1507
+ return undefined;
1508
+ }
1509
+ for (let i = 0; i < targetData.length; i++) {
1510
+ const child = targetData[i];
1511
+ if (!child || !isNode(child, N.Selector)) {
1512
+ continue;
1513
+ }
1514
+ if (isNode(child, N.Combinator)) {
1515
+ continue;
1516
+ }
1517
+
1518
+ const childMatch = selectorMatch(find, child, parent, context);
1519
+ if (childMatch.crossesAmpersand) {
1520
+ continue;
1521
+ }
1522
+ if (!childMatch.fullMatch && !childMatch.partialMatch) {
1523
+ continue;
1524
+ }
1525
+ matchedChildren.push({ index: i, child });
1526
+ }
1527
+
1528
+ if (matchedChildren.length < 2) {
1529
+ return undefined;
1530
+ }
1531
+
1532
+ let currentTarget = target;
1533
+ let crossedAmpersand = false;
1534
+ let anyChanged = false;
1535
+ for (const { index, child } of matchedChildren) {
1536
+ const childValueBefore = child.valueOf();
1537
+ let replacement: Selector | undefined;
1538
+
1539
+ if (isNode(target, N.SelectorList)) {
1540
+ const result = tryExtendSelector(child, find, extendWith, true, parent, context);
1541
+ if (!result.error) {
1542
+ replacement = result.value;
1543
+ crossedAmpersand ||= !!result.value.hoistToRoot;
1544
+ }
1545
+ } else if (isNode(target, N.CompoundSelector)) {
1546
+ const outsideMembers = getCompoundMembersOutsideRange(
1547
+ target,
1548
+ index,
1549
+ index,
1550
+ undefined
1551
+ );
1552
+ const conflict = getCompoundConflictError(outsideMembers, extendWith);
1553
+ if (conflict) {
1554
+ return { value: target, error: conflict, isChanged: false };
1555
+ }
1556
+
1557
+ if (isNode(child, N.CompoundSelector | N.ComplexSelector | N.PseudoSelector | N.SelectorList)) {
1558
+ const result = tryExtendSelector(child, find, extendWith, true, parent, context);
1559
+ if (!result.error) {
1560
+ replacement = result.value;
1561
+ crossedAmpersand ||= !!result.value.hoistToRoot;
1562
+ }
1563
+ } else {
1564
+ replacement = wrapSelectorInIs(child, stripRedundantCompoundContext(extendWith, outsideMembers));
1565
+ }
1566
+ } else {
1567
+ if (isNode(child, N.CompoundSelector | N.ComplexSelector | N.PseudoSelector | N.SelectorList)) {
1568
+ const result = tryExtendSelector(child, find, extendWith, true, parent, context);
1569
+ if (!result.error) {
1570
+ replacement = result.value;
1571
+ crossedAmpersand ||= !!result.value.hoistToRoot;
1572
+ }
1573
+ } else {
1574
+ replacement = wrapSelectorInIs(child, extendWith);
1575
+ }
1576
+ }
1577
+
1578
+ if (!replacement) {
1579
+ continue;
1580
+ }
1581
+ if (replacement !== child || replacement.valueOf() !== childValueBefore) {
1582
+ anyChanged = true;
1583
+ }
1584
+ currentTarget = setSelectorContainerValueAt(currentTarget, index, replacement);
1585
+ }
1586
+
1587
+ if (crossedAmpersand) {
1588
+ currentTarget.hoistToRoot = true;
1589
+ }
1590
+
1591
+ return finalize(createSuccessResult(currentTarget, anyChanged));
1592
+ }
1593
+
1594
+ /**
1595
+ * Attempts to extend `target` using `find` and `extendWith`.
1596
+ *
1597
+ * Exact mode adds a new alternative only when `selectorMatch()` reports a full
1598
+ * match. Partial mode wraps only genuinely partial matches; if partial mode
1599
+ * finds an exact route, it also adds a new alternative instead of generating a
1600
+ * redundant `:is(...)` wrapper.
1601
+ *
1602
+ * The deciding question is whether the successful match stays attached to the
1603
+ * same selector component or crosses a component boundary. When the match
1604
+ * remains on the same component, the rewrite should append to that component's
1605
+ * alternate container. When it crosses a component boundary, the rewrite may
1606
+ * need a generated `:is(...)` wrapper to preserve the unmatched surrounding
1607
+ * structure.
1608
+ *
1609
+ * Put differently: before introducing a generated `:is(...)`, first ask
1610
+ * whether `selectorMatch()` found an exact full match route for the selector
1611
+ * component being rewritten. If it did, the correct shape is a selector list
1612
+ * or an append into an existing alternate container.
1613
+ *
1614
+ * When `parent` is provided, it is passed directly into `selectorMatch()` as a
1615
+ * non-mutating implicit ampersand context. This allows extend callers to search
1616
+ * authored selectors against their resolved parent context without first
1617
+ * materializing implicit ampersand wrappers into the target tree.
1618
+ *
1619
+ * Nested `tryExtendSelector()` calls in this file are still structural rewrite
1620
+ * helpers on already-selected child selectors. They may reuse the same
1621
+ * `parent` when that child is part of the same authored selector route and
1622
+ * therefore must preserve the same ampersand resolution context, but they do
1623
+ * not widen the search into unrelated outer contexts.
1624
+ *
1625
+ * This implementation is intentionally being rebuilt in tiny slices on top of
1626
+ * `selectorMatch()`. Unsupported rewrite shapes currently return `NOT_FOUND`
1627
+ * rather than falling back to legacy extend behavior.
1628
+ */
1629
+ export function tryExtendSelector(
1630
+ target: Selector,
1631
+ find: Selector,
1632
+ extendWith: Selector,
1633
+ partial: boolean,
1634
+ parent?: Selector,
1635
+ context?: Context
1636
+ ): ExtendResult {
1637
+ const finalize = (result: ExtendResult): ExtendResult => {
1638
+ if (!result.error && parent && result.value.hoistToRoot) {
1639
+ return createSuccessResult(materializeAmpersandsForHoist(result.value, parent));
1640
+ }
1641
+ return result;
1642
+ };
1643
+
1644
+ const match = selectorMatch(find, target, parent, context);
1645
+ if (!partial) {
1646
+ if (!match.fullMatch) {
1647
+ return createErrorResult(target, ExtendErrorType.NOT_FOUND, 'Selector not found');
1648
+ }
1649
+
1650
+ return createExactExtendResult(target, extendWith, parent, match.crossesAmpersand, finalize);
1651
+ }
1652
+
1653
+ if (!match.partialMatch || match.matches.length === 0) {
1654
+ const noPartialMatchResult = tryHandleNoPartialMatch(target, find, extendWith, parent, finalize, context);
1655
+ if (noPartialMatchResult) {
1656
+ return noPartialMatchResult;
1657
+ }
1658
+
1659
+ return createErrorResult(target, ExtendErrorType.NOT_FOUND, 'Selector not found');
1660
+ }
1661
+
1662
+ const earlyDirectListAppend = tryAppendToDirectSelectorListOnFullMatch(target, find, extendWith, parent, context);
1663
+ if (earlyDirectListAppend) {
1664
+ return finalize(earlyDirectListAppend);
1665
+ }
1666
+
1667
+ const multiDirectChildFullMatch = tryHandleMultiDirectChildFullMatches(
1668
+ target,
1669
+ find,
1670
+ extendWith,
1671
+ parent,
1672
+ finalize,
1673
+ context
1674
+ );
1675
+ if (multiDirectChildFullMatch) {
1676
+ return multiDirectChildFullMatch;
1677
+ }
1678
+
1679
+ const location = getPreferredMatchLocation(target, match);
1680
+ const crossedAmpersand = !!(location.crossesAmpersand || match.crossesAmpersand);
1681
+ const markTargetHoist = (extra = false): void => {
1682
+ if (crossedAmpersand || extra) {
1683
+ target.hoistToRoot = true;
1684
+ }
1685
+ };
1686
+ const finishNested = (
1687
+ result: ExtendResult | undefined,
1688
+ extraHoist = false
1689
+ ): ExtendResult | undefined => {
1690
+ if (!result) {
1691
+ return undefined;
1692
+ }
1693
+
1694
+ markTargetHoist(extraHoist || !!result.value.hoistToRoot);
1695
+ return finalize(result);
1696
+ };
1697
+ const finishRootReplacement = (
1698
+ replacement: Selector,
1699
+ preserveRootKinds: number
1700
+ ): ExtendResult => {
1701
+ if (replacement === target) {
1702
+ return finalize(createSuccessResult(target, false));
1703
+ }
1704
+ if (isNode(replacement, preserveRootKinds)) {
1705
+ const rootTarget = getSelectorChildren(target) ? target : undefined;
1706
+ if (!rootTarget) {
1707
+ return finalize(createSuccessResult(replacement));
1708
+ }
1709
+ const nextTarget = setSelectorContainerValue(
1710
+ rootTarget,
1711
+ [...getSelectorChildren(replacement)!]
1712
+ );
1713
+ if (crossedAmpersand) {
1714
+ nextTarget.hoistToRoot = true;
1715
+ }
1716
+ return finalize(createSuccessResult(nextTarget));
1717
+ }
1718
+
1719
+ if (crossedAmpersand) {
1720
+ replacement.hoistToRoot = true;
1721
+ }
1722
+ return finalize(createSuccessResult(replacement));
1723
+ };
1724
+ const finishStructuralChildRewrite = (
1725
+ child: Selector | undefined
1726
+ ): ExtendResult | undefined => {
1727
+ if (!child) {
1728
+ return undefined;
1729
+ }
1730
+
1731
+ const nested = tryExtendSelector(child, find, extendWith, true, parent, context);
1732
+ const nextTarget = nested.error ? undefined : replaceDirectSelectorChild(target, child, nested.value);
1733
+ if (!nextTarget) {
1734
+ return undefined;
1735
+ }
1736
+
1737
+ if (crossedAmpersand || nested.value.hoistToRoot) {
1738
+ nextTarget.hoistToRoot = true;
1739
+ }
1740
+ return finalize(createSuccessResult(nextTarget, nested.isChanged));
1741
+ };
1742
+ const tryHandleRootSingleSlotPartial = (): ExtendResult | undefined => {
1743
+ const rootIsOrdered = isNode(target, N.ComplexSelector) || isNode(target, N.CompoundSelector);
1744
+ const targetChildren = getSelectorChildren(target);
1745
+ const orderedTarget = getComplexSelector(target) ?? getCompoundSelector(target);
1746
+ if (
1747
+ !rootIsOrdered
1748
+ || location.containingNode !== target
1749
+ || location.startIndex === undefined
1750
+ || location.endIndex === undefined
1751
+ || location.startIndex !== location.endIndex
1752
+ || (
1753
+ targetChildren !== undefined
1754
+ && isNode(targetChildren[location.startIndex]!, N.CompoundSelector)
1755
+ && location.matchedIndices
1756
+ && location.matchedIndices.length > 0
1757
+ )
1758
+ ) {
1759
+ return undefined;
1760
+ }
1761
+
1762
+ const compoundTarget = getCompoundSelector(target);
1763
+ const compoundOutsideMembers = compoundTarget
1764
+ ? getCompoundMembersOutsideRange(
1765
+ compoundTarget,
1766
+ location.startIndex,
1767
+ location.endIndex,
1768
+ location.matchedIndices
1769
+ )
1770
+ : undefined;
1771
+
1772
+ if (compoundTarget) {
1773
+ const conflict = getCompoundConflictError(compoundOutsideMembers!, extendWith);
1774
+ if (conflict) {
1775
+ return { value: target, error: conflict, isChanged: false };
1776
+ }
1777
+ }
1778
+
1779
+ const existing = targetChildren![location.startIndex]!;
1780
+ const nestedIsListAppend = tryAppendToDirectSelectorListOnFullMatch(existing, find, extendWith, parent, context);
1781
+ if (nestedIsListAppend) {
1782
+ const nextTarget = setSelectorContainerValueAt(
1783
+ orderedTarget!,
1784
+ location.startIndex,
1785
+ nestedIsListAppend.value
1786
+ );
1787
+ if (crossedAmpersand || nestedIsListAppend.value.hoistToRoot) {
1788
+ nextTarget.hoistToRoot = true;
1789
+ }
1790
+ return finalize(createSuccessResult(nextTarget));
1791
+ }
1792
+
1793
+ if (
1794
+ isNode(existing, N.PseudoSelector | N.SelectorList | N.CompoundSelector | N.ComplexSelector)
1795
+ && !isNode(existing, N.CompoundSelector)
1796
+ ) {
1797
+ const nested = tryExtendSelector(existing, find, extendWith, true, parent, context);
1798
+ if (!nested.error) {
1799
+ const nextTarget = setSelectorContainerValueAt(
1800
+ orderedTarget!,
1801
+ location.startIndex,
1802
+ nested.value
1803
+ );
1804
+ if (crossedAmpersand || nested.value.hoistToRoot) {
1805
+ nextTarget.hoistToRoot = true;
1806
+ }
1807
+ return finalize(createSuccessResult(nextTarget, nested.isChanged));
1808
+ }
1809
+ }
1810
+
1811
+ const wrapped = wrapSelectorInIs(existing, stripRedundantCompoundContext(extendWith, compoundOutsideMembers ?? []));
1812
+ const nextTarget = setSelectorContainerValueAt(
1813
+ orderedTarget!,
1814
+ location.startIndex,
1815
+ wrapped
1816
+ );
1817
+ if (crossedAmpersand) {
1818
+ nextTarget.hoistToRoot = true;
1819
+ }
1820
+ return finalize(createSuccessResult(nextTarget, wrapped !== existing));
1821
+ };
1822
+ const tryHandleRootMultiSlotPartial = (): ExtendResult | undefined => {
1823
+ const compoundTarget = getCompoundSelector(target);
1824
+ if (
1825
+ compoundTarget
1826
+ && location.containingNode === target
1827
+ && location.startIndex !== undefined
1828
+ && location.endIndex !== undefined
1829
+ && location.startIndex < location.endIndex
1830
+ ) {
1831
+ const crossedAmpersandParent = getCrossedAmpersandParent(location);
1832
+ if (crossedAmpersandParent) {
1833
+ const replacement = wrapResolvedCompoundSpan(
1834
+ compoundTarget,
1835
+ location.startIndex,
1836
+ location.endIndex,
1837
+ extendWith,
1838
+ crossedAmpersandParent
1839
+ );
1840
+ return finishRootReplacement(replacement, N.ComplexSelector | N.CompoundSelector);
1841
+ }
1842
+
1843
+ const outsideMembers = getCompoundMembersOutsideRange(
1844
+ compoundTarget,
1845
+ location.startIndex,
1846
+ location.endIndex,
1847
+ location.matchedIndices
1848
+ );
1849
+ const conflict = getCompoundConflictError(outsideMembers, extendWith);
1850
+ if (conflict) {
1851
+ return { value: target, error: conflict, isChanged: false };
1852
+ }
1853
+
1854
+ const pulledIntoNestedIs = tryPullCompoundMatchIntoNestedIsBranch(compoundTarget, location, find, extendWith, context);
1855
+ if (pulledIntoNestedIs) {
1856
+ return finalize(pulledIntoNestedIs);
1857
+ }
1858
+
1859
+ const replacement = wrapCompoundMatchRange(
1860
+ compoundTarget,
1861
+ location.startIndex,
1862
+ location.endIndex,
1863
+ location.matchedIndices,
1864
+ extendWith
1865
+ );
1866
+ return finishRootReplacement(replacement, N.ComplexSelector | N.CompoundSelector);
1867
+ }
1868
+
1869
+ const complexTarget = getComplexSelector(target);
1870
+ if (
1871
+ complexTarget
1872
+ && location.containingNode === target
1873
+ && location.startIndex !== undefined
1874
+ && location.endIndex !== undefined
1875
+ && location.startIndex < location.endIndex
1876
+ ) {
1877
+ const crossedAmpersandParent = getCrossedAmpersandParent(location)
1878
+ ?? (crossedAmpersand ? parent : undefined);
1879
+ if (crossedAmpersandParent) {
1880
+ const replacement = wrapResolvedOrderedSpanWithTailRemainder(
1881
+ complexTarget,
1882
+ location.startIndex,
1883
+ location.endIndex,
1884
+ extendWith,
1885
+ crossedAmpersandParent,
1886
+ getLastOrderedSelector(find),
1887
+ location,
1888
+ context
1889
+ );
1890
+ if (replacement) {
1891
+ return finishRootReplacement(replacement, N.ComplexSelector);
1892
+ }
1893
+ }
1894
+
1895
+ const replacement = wrapOrderedMatchRange(complexTarget, location.startIndex, location.endIndex, extendWith);
1896
+ return finishRootReplacement(replacement, N.ComplexSelector);
1897
+ }
1898
+
1899
+ return undefined;
1900
+ };
1901
+ const tryHandleDirectChildContainingNodePartial = (): ExtendResult | undefined => {
1902
+ const containingNode = location.containingNode;
1903
+ const directChild = isNode(containingNode, N.Selector)
1904
+ ? (
1905
+ getContainingDirectChildSelector(target, containingNode)
1906
+ ?? getStructurallyMatchingDirectChildSelector(target, containingNode)
1907
+ )
1908
+ : undefined;
1909
+ if (!directChild) {
1910
+ return undefined;
1911
+ }
1912
+
1913
+ let replacement: Selector;
1914
+ if (
1915
+ isNode(directChild, N.CompoundSelector)
1916
+ && location.startIndex !== undefined
1917
+ && location.endIndex !== undefined
1918
+ ) {
1919
+ const crossedAmpersandParent = getCrossedAmpersandParent(location);
1920
+ if (crossedAmpersandParent) {
1921
+ replacement = wrapSelectorInIs(
1922
+ materializeAmpersandsForHoist(directChild, crossedAmpersandParent),
1923
+ extendWith
1924
+ );
1925
+ } else {
1926
+ const pulledIntoNestedIs = tryPullCompoundMatchIntoNestedIsBranch(directChild, location, find, extendWith, context);
1927
+ if (pulledIntoNestedIs) {
1928
+ replacement = pulledIntoNestedIs.value;
1929
+ } else {
1930
+ const conflict = getCompoundConflictError(
1931
+ getCompoundMembersOutsideRange(
1932
+ directChild,
1933
+ location.startIndex,
1934
+ location.endIndex,
1935
+ location.matchedIndices
1936
+ ),
1937
+ extendWith
1938
+ );
1939
+ if (conflict) {
1940
+ return { value: target, error: conflict, isChanged: false };
1941
+ }
1942
+
1943
+ replacement = wrapCompoundMatchRange(
1944
+ directChild,
1945
+ location.startIndex,
1946
+ location.endIndex,
1947
+ location.matchedIndices,
1948
+ extendWith
1949
+ );
1950
+ }
1951
+ }
1952
+ } else {
1953
+ const nestedDirectChild = isNode(directChild, N.PseudoSelector | N.SelectorList | N.ComplexSelector)
1954
+ ? tryExtendSelector(directChild, find, extendWith, true, parent, context)
1955
+ : undefined;
1956
+ if (nestedDirectChild && !nestedDirectChild.error) {
1957
+ replacement = nestedDirectChild.value;
1958
+ } else {
1959
+ const compoundTarget = getCompoundSelector(target);
1960
+ if (compoundTarget) {
1961
+ const childIndex = compoundTarget.get('value').findIndex(node => node === containingNode);
1962
+ if (childIndex !== -1) {
1963
+ const conflict = getCompoundConflictError(
1964
+ getCompoundMembersOutsideRange(
1965
+ compoundTarget,
1966
+ childIndex,
1967
+ childIndex,
1968
+ undefined
1969
+ ),
1970
+ extendWith
1971
+ );
1972
+ if (conflict) {
1973
+ return { value: target, error: conflict, isChanged: false };
1974
+ }
1975
+ }
1976
+ }
1977
+
1978
+ replacement = wrapSelectorInIs(directChild, extendWith);
1979
+ }
1980
+ }
1981
+
1982
+ const childChanged = replacement !== directChild;
1983
+ const nextTarget = replaceDirectSelectorChild(target, directChild, replacement);
1984
+ if (nextTarget) {
1985
+ if (crossedAmpersand) {
1986
+ nextTarget.hoistToRoot = true;
1987
+ }
1988
+ return finalize(createSuccessResult(nextTarget, childChanged));
1989
+ }
1990
+
1991
+ return undefined;
1992
+ };
1993
+ const directPseudoArg = getDirectPseudoArg(target);
1994
+ const directIsArg = getDirectIsArg(target);
1995
+ if (location.exact) {
1996
+ const directListAppend = tryAppendToDirectSelectorListOnFullMatch(target, find, extendWith, parent);
1997
+ if (directListAppend) {
1998
+ markTargetHoist(!!directListAppend.value.hoistToRoot);
1999
+ return finalize(directListAppend);
2000
+ }
2001
+
2002
+ if (
2003
+ location.containingNode === target
2004
+ && isNode(target, N.ComplexSelector)
2005
+ ) {
2006
+ const resolved = resolveAmpersandTarget(target, parent);
2007
+ if (resolved) {
2008
+ const exactResult = createAlternativeSelector(resolved, extendWith);
2009
+ exactResult.hoistToRoot = true;
2010
+ markTargetHoist(true);
2011
+ return finalize(createSuccessResult(exactResult));
2012
+ }
2013
+ }
2014
+
2015
+ if (location.containingNode === target) {
2016
+ const nestedIsResult = directIsArg
2017
+ ? tryExtendDirectChildSelector(target, directIsArg, find, extendWith, parent, crossedAmpersand, context)
2018
+ : undefined;
2019
+ const finishedNestedIs = finishNested(nestedIsResult);
2020
+ if (finishedNestedIs) {
2021
+ return finishedNestedIs;
2022
+ }
2023
+
2024
+ const nestedPseudoResult = directPseudoArg && directPseudoArg === location.containingNode
2025
+ ? tryExtendDirectChildSelector(target, location.containingNode, find, extendWith, parent, crossedAmpersand, context)
2026
+ : undefined;
2027
+ const finishedNestedPseudo = finishNested(nestedPseudoResult);
2028
+ if (finishedNestedPseudo) {
2029
+ return finishedNestedPseudo;
2030
+ }
2031
+
2032
+ const nestedListResult = isNode(target, N.SelectorList)
2033
+ ? tryExtendDirectChildSelector(target, getSingleMatchedDirectChild(target, location), find, extendWith, parent, crossedAmpersand, context)
2034
+ : undefined;
2035
+ const finishedNestedList = finishNested(nestedListResult);
2036
+ if (finishedNestedList) {
2037
+ return finishedNestedList;
2038
+ }
2039
+
2040
+ const nestedOrderedChildResult = (isNode(target, N.ComplexSelector) || isNode(target, N.CompoundSelector))
2041
+ ? tryExtendDirectChildSelector(target, getSingleMatchedDirectChild(target, location), find, extendWith, parent, crossedAmpersand, context)
2042
+ : undefined;
2043
+ const finishedNestedOrderedChild = finishNested(nestedOrderedChildResult);
2044
+ if (finishedNestedOrderedChild) {
2045
+ return finishedNestedOrderedChild;
2046
+ }
2047
+
2048
+ const exactTarget = crossedAmpersand
2049
+ ? materializeCrossedTarget(target, parent) ?? target
2050
+ : target;
2051
+ const exactResult = createAlternativeSelector(exactTarget, extendWith);
2052
+ if (crossedAmpersand) {
2053
+ exactResult.hoistToRoot = true;
2054
+ markTargetHoist(true);
2055
+ }
2056
+ return finalize(createSuccessResult(exactResult));
2057
+ }
2058
+
2059
+ const nestedPseudoListAppend = isNode(location.containingNode, N.Selector)
2060
+ ? tryAppendToContainingSelectorList(target, location.containingNode, extendWith)
2061
+ : undefined;
2062
+ const finishedNestedPseudoListAppend = finishNested(nestedPseudoListAppend);
2063
+ if (finishedNestedPseudoListAppend) {
2064
+ return finishedNestedPseudoListAppend;
2065
+ }
2066
+
2067
+ if (location.containingNode.parent === target) {
2068
+ if (isNode(target, N.SelectorList)) {
2069
+ const rewrittenListChild = isNode(location.containingNode, N.Selector)
2070
+ ? finishStructuralChildRewrite(location.containingNode)
2071
+ : undefined;
2072
+ if (rewrittenListChild) {
2073
+ return rewrittenListChild;
2074
+ }
2075
+
2076
+ return finalize(createSuccessResult(createAlternativeSelector(target, extendWith)));
2077
+ }
2078
+
2079
+ const rewrittenChild = isNode(location.containingNode, N.Selector)
2080
+ ? finishStructuralChildRewrite(location.containingNode)
2081
+ : undefined;
2082
+ if (rewrittenChild) {
2083
+ return rewrittenChild;
2084
+ }
2085
+ }
2086
+ }
2087
+
2088
+ const nestedPseudoResult = directPseudoArg && directPseudoArg === location.containingNode
2089
+ ? tryExtendDirectChildSelector(target, location.containingNode, find, extendWith, parent, crossedAmpersand, context)
2090
+ : undefined;
2091
+ const finishedNestedPseudo = finishNested(nestedPseudoResult);
2092
+ if (finishedNestedPseudo) {
2093
+ return finishedNestedPseudo;
2094
+ }
2095
+
2096
+ if (location.containingNode === target) {
2097
+ const nestedIsResult = directIsArg
2098
+ ? tryExtendDirectChildSelector(target, directIsArg, find, extendWith, parent, crossedAmpersand, context)
2099
+ : undefined;
2100
+ const finishedNestedIs = finishNested(nestedIsResult);
2101
+ if (finishedNestedIs) {
2102
+ return finishedNestedIs;
2103
+ }
2104
+
2105
+ const nestedListResult = isNode(target, N.SelectorList)
2106
+ ? tryExtendDirectChildSelector(target, getSingleMatchedDirectChild(target, location), find, extendWith, parent, crossedAmpersand, context)
2107
+ : undefined;
2108
+ const finishedNestedList = finishNested(nestedListResult);
2109
+ if (finishedNestedList) {
2110
+ return finishedNestedList;
2111
+ }
2112
+ }
2113
+
2114
+ const rootSingleSlotPartial = tryHandleRootSingleSlotPartial();
2115
+ if (rootSingleSlotPartial) {
2116
+ return rootSingleSlotPartial;
2117
+ }
2118
+
2119
+ const rootMultiSlotPartial = tryHandleRootMultiSlotPartial();
2120
+ if (rootMultiSlotPartial) {
2121
+ return rootMultiSlotPartial;
2122
+ }
2123
+
2124
+ const directChildContainingNodePartial = tryHandleDirectChildContainingNodePartial();
2125
+ if (directChildContainingNodePartial) {
2126
+ return directChildContainingNodePartial;
2127
+ }
2128
+
2129
+ const containingChild = getContainingDirectChildSelector(target, location.containingNode);
2130
+ if (containingChild) {
2131
+ const nested = tryExtendDirectChildSelector(target, containingChild, find, extendWith, parent, crossedAmpersand, context);
2132
+ const finishedNested = finishNested(nested);
2133
+ if (finishedNested) {
2134
+ return finishedNested;
2135
+ }
2136
+ }
2137
+
2138
+ return createErrorResult(target, ExtendErrorType.NOT_FOUND, 'Partial extend shape not implemented yet');
2139
+ }