1- // @ts -check
21const { Rule, AtRule } = require ( 'postcss' )
32let parser = require ( 'postcss-selector-parser' )
43
5- /** @typedef {import('postcss').Container } Container */
6- /** @typedef {import('postcss').ChildNode } ChildNode */
7- /** @typedef {import('postcss').Comment } Comment */
8- /** @typedef {import('postcss').Declaration } Declaration */
9- /** @typedef {import('postcss').Rule } PostcssRule */
10- /** @typedef {typeof import('postcss').Rule } RuleConstructor */
11- /** @typedef {parser.Root } Root */
12- /** @typedef {parser.Node } Node */
13- /** @typedef {parser.Selector } Selector */
14- /** @typedef {Record<string, true> } RuleMap Simple lookup table for \@-rules */
15-
164/**
175 * Run a selector string through postcss-selector-parser
18- *
19- * @param {string } rawSelector
20- * @param {PostcssRule } [rule]
21- * @returns {Selector }
226 */
237function parse ( rawSelector , rule ) {
24- /** @type {Root | undefined } */
258 let nodes
269 try {
2710 parser ( parsed => {
@@ -34,54 +17,41 @@ function parse(rawSelector, rule) {
3417 throw rule ? rule . error ( e . message ) : e
3518 }
3619 }
37- // Should be safe, but @ts-check can't deduce the side-effect
38- // triggered by `saver.processSync(str)`
39- return /** @type {Root } */ ( nodes ) . at ( 0 )
20+ return nodes . at ( 0 )
4021}
4122
4223/**
4324 * Replaces the "&" token in a node's selector with the parent selector
4425 * similar to what SCSS does.
4526 *
4627 * Mutates the nodes list
47- *
48- * @param {Extract<Node, { nodes: Array }> } nodes
49- * @param {Selector } parent
50- * @returns {boolean } Indicating whether a replacement took place or not.
5128 */
5229function interpolateAmpInSelector ( nodes , parent ) {
5330 let replaced = false
54- nodes . each (
55- /** @type {Node } */ node => {
56- if ( node . type === 'nesting' ) {
57- let clonedParent = parent . clone ( { } )
58- if ( node . value !== '&' ) {
59- node . replaceWith (
60- parse ( node . value . replace ( '&' , clonedParent . toString ( ) ) )
61- )
62- } else {
63- node . replaceWith ( clonedParent )
64- }
31+ nodes . each ( node => {
32+ if ( node . type === 'nesting' ) {
33+ let clonedParent = parent . clone ( { } )
34+ if ( node . value !== '&' ) {
35+ node . replaceWith (
36+ parse ( node . value . replace ( '&' , clonedParent . toString ( ) ) )
37+ )
38+ } else {
39+ node . replaceWith ( clonedParent )
40+ }
41+ replaced = true
42+ } else if ( 'nodes' in node && node . nodes ) {
43+ if ( interpolateAmpInSelector ( node , parent ) ) {
6544 replaced = true
66- } else if ( 'nodes' in node && node . nodes ) {
67- if ( interpolateAmpInSelector ( node , parent ) ) {
68- replaced = true
69- }
7045 }
7146 }
72- )
47+ } )
7348 return replaced
7449}
7550
7651/**
7752 * Combines parent and child selectors, in a SCSS-like way
78- *
79- * @param {PostcssRule } parent
80- * @param {PostcssRule } child
81- * @returns {Array<string> } An array of new, merged selectors
8253 */
8354function mergeSelectors ( parent , child ) {
84- /** @type {Array<string> } */
8555 let merged = [ ]
8656 parent . selectors . forEach ( sel => {
8757 let parentNode = parse ( sel , parent )
@@ -93,10 +63,8 @@ function mergeSelectors(parent, child) {
9363 let node = parse ( selector , child )
9464 let replaced = interpolateAmpInSelector ( node , parentNode )
9565 if ( ! replaced ) {
96- // NOTE: The type definitions for `postcss-selector-parser` seem to be
97- // badly outdated.
98- node . prepend ( /** @type {any } */ ( parser . combinator ( { value : ' ' } ) ) )
99- node . prepend ( /** @type {Selector } */ ( parentNode . clone ( { } ) ) )
66+ node . prepend ( parser . combinator ( { value : ' ' } ) )
67+ node . prepend ( parentNode . clone ( { } ) )
10068 }
10169 merged . push ( node . toString ( ) )
10270 } )
@@ -106,10 +74,6 @@ function mergeSelectors(parent, child) {
10674
10775/**
10876 * Move a child and its preceeding comment(s) to after "after"
109- *
110- * @param {ChildNode } child
111- * @param {ChildNode } after
112- * @returns {ChildNode } updated "after" node
11377 */
11478function breakOut ( child , after ) {
11579 let prev = child . prev ( )
@@ -122,17 +86,8 @@ function breakOut(child, after) {
12286 return child
12387}
12488
125- /**
126- * @param {RuleMap } bubble
127- */
12889function createFnAtruleChilds ( bubble ) {
129- /**
130- * @param {PostcssRule } rule
131- * @param {AtRule } atrule
132- * @param {boolean } bubbling
133- */
13490 return function atruleChilds ( rule , atrule , bubbling , mergeSels = bubbling ) {
135- /** @type {Array<ChildNode> } */
13691 let children = [ ]
13792 atrule . each ( child => {
13893 if ( child . type === 'rule' && bubbling ) {
@@ -161,11 +116,6 @@ function createFnAtruleChilds(bubble) {
161116 }
162117}
163118
164- /**
165- * @param {string } selector
166- * @param {Array<ChildNode> } declarations
167- * @param {ChildNode } after
168- */
169119function pickDeclarations ( selector , declarations , after ) {
170120 let parent = new Rule ( {
171121 selector,
@@ -176,12 +126,7 @@ function pickDeclarations(selector, declarations, after) {
176126 return parent
177127}
178128
179- /**
180- * @param {Array<string> } defaults,
181- * @param {Array<string> } [custom]
182- */
183129function atruleNames ( defaults , custom ) {
184- /** @type {RuleMap } */
185130 let list = { }
186131 for ( let name of defaults ) {
187132 list [ name ] = true
@@ -194,13 +139,6 @@ function atruleNames(defaults, custom) {
194139 return list
195140}
196141
197- /** @typedef {{ type: 'basic', selector?: string, escapes?: never } } AtRootBParams */
198- /** @typedef {{ type: 'withrules', escapes: (rule: string) => boolean, selector?: never } } AtRootWParams */
199- /** @typedef {{ type: 'unknown', selector?: never, escapes?: never } } AtRootUParams */
200- /** @typedef {{ type: 'noop', selector?: never, escapes?: never } } AtRootNParams */
201- /** @typedef {AtRootBParams | AtRootWParams | AtRootNParams | AtRootUParams } AtRootParams */
202-
203- /** @type {(params: string) => AtRootParams } */
204142function parseRootRuleParams ( params ) {
205143 params = params . trim ( )
206144 let braceBlock = params . match ( / ^ \( ( .* ) \) $ / )
@@ -210,7 +148,6 @@ function parseRootRuleParams(params) {
210148 let bits = braceBlock [ 1 ] . match ( / ^ ( w i t h (?: o u t ) ? ) : ( .+ ) $ / )
211149 if ( bits ) {
212150 let allowlist = bits [ 1 ] === 'with'
213- /** @type {RuleMap } */
214151 let rules = Object . fromEntries (
215152 bits [ 2 ]
216153 . trim ( )
@@ -236,52 +173,39 @@ function parseRootRuleParams(params) {
236173 return { type : 'unknown' }
237174}
238175
239- /**
240- * @param {AtRule } leaf
241- * @returns {Array<AtRule> }
242- */
243176function getAncestorRules ( leaf ) {
244- /** @type {Array<AtRule> } */
245- const lineage = [ ]
246- /** @type {Container | ChildNode | Document | undefined } */
177+ let lineage = [ ]
247178 let parent = leaf . parent
248179
249180 while ( parent && parent instanceof AtRule ) {
250- lineage . push ( /** @type { AtRule } */ ( parent ) )
181+ lineage . push ( parent )
251182 parent = parent . parent
252183 }
253184 return lineage
254185}
255186
256- /**
257- * @param {AtRule } rule
258- */
259187function unwrapRootRule ( rule ) {
260- const escapes = rule [ rootRuleEscapes ]
188+ let escapes = rule [ rootRuleEscapes ]
261189
262190 if ( ! escapes ) {
263191 rule . after ( rule . nodes )
264192 } else {
265- const nodes = rule . nodes
193+ let nodes = rule . nodes
266194
267- /** @type {AtRule | undefined } */
268195 let topEscaped
269196 let topEscapedIdx = - 1
270- /** @type {AtRule | undefined } */
271197 let breakoutLeaf
272- /** @type {AtRule | undefined } */
273198 let breakoutRoot
274- /** @type {AtRule | undefined } */
275199 let clone
276200
277- const lineage = getAncestorRules ( rule )
201+ let lineage = getAncestorRules ( rule )
278202 lineage . forEach ( ( parent , i ) => {
279203 if ( escapes ( parent . name ) ) {
280204 topEscaped = parent
281205 topEscapedIdx = i
282206 breakoutRoot = clone
283207 } else {
284- const oldClone = clone
208+ let oldClone = clone
285209 clone = parent . clone ( { nodes : [ ] } )
286210 oldClone && clone . append ( oldClone )
287211 breakoutLeaf = breakoutLeaf || clone
@@ -293,20 +217,18 @@ function unwrapRootRule(rule) {
293217 } else if ( ! breakoutRoot ) {
294218 topEscaped . after ( nodes )
295219 } else {
296- const leaf = /** @type { AtRule } */ ( breakoutLeaf )
220+ let leaf = breakoutLeaf
297221 leaf . append ( nodes )
298222 topEscaped . after ( breakoutRoot )
299223 }
300224
301225 if ( rule . next ( ) && topEscaped ) {
302- /** @type {AtRule | undefined } */
303226 let restRoot
304227 lineage . slice ( 0 , topEscapedIdx + 1 ) . forEach ( ( parent , i , arr ) => {
305- const oldRoot = restRoot
228+ let oldRoot = restRoot
306229 restRoot = parent . clone ( { nodes : [ ] } )
307230 oldRoot && restRoot . append ( oldRoot )
308231
309- /** @type {Array<ChildNode> } */
310232 let nextSibs = [ ]
311233 let _child = arr [ i - 1 ] || rule
312234 let next = _child . next ( )
@@ -326,12 +248,9 @@ function unwrapRootRule(rule) {
326248const rootRuleMergeSel = Symbol ( 'rootRuleMergeSel' )
327249const rootRuleEscapes = Symbol ( 'rootRuleEscapes' )
328250
329- /**
330- * @param {AtRule } rule
331- */
332251function normalizeRootRule ( rule ) {
333252 let { params } = rule
334- const { type, selector, escapes } = parseRootRuleParams ( params )
253+ let { type, selector, escapes } = parseRootRuleParams ( params )
335254 if ( type === 'unknown' ) {
336255 throw rule . error (
337256 `Unknown @${ rule . name } parameter ${ JSON . stringify ( params ) } `
@@ -348,9 +267,6 @@ function normalizeRootRule(rule) {
348267
349268const hasRootRule = Symbol ( 'hasRootRule' )
350269
351- // ---------------------------------------------------------------------------
352-
353- /** @type {import('./').Nested } */
354270module . exports = ( opts = { } ) => {
355271 let bubble = atruleNames ( [ 'media' , 'supports' , 'layer' ] , opts . bubble )
356272 let atruleChilds = createFnAtruleChilds ( bubble )
@@ -379,10 +295,8 @@ module.exports = (opts = {}) => {
379295
380296 Rule ( rule ) {
381297 let unwrapped = false
382- /** @type {ChildNode } */
383298 let after = rule
384299 let copyDeclarations = false
385- /** @type {Array<ChildNode> } */
386300 let declarations = [ ]
387301
388302 rule . each ( child => {
0 commit comments