Skip to content

Commit a9a91e7

Browse files
Correction of the work with comments and general improvements (#163)
* Changed the if to switch construction in the Rules method. * The duplicate code has been removed. * Simplified the atruleNames function * Minor changes. * Added a fix for not deleting comments * Changing the tests Added a test to check the work with comments The existing tests have been changed because they contained incorrect data. * Added code for processing comments in the rules. * Updated tests. * Added processing for new lines. * Updated tests, added the use of new lines * The readability of the test has been improved. * Added a test to save the father's comment * Edit to correct the lint error.
1 parent 013abd3 commit a9a91e7

File tree

2 files changed

+129
-70
lines changed

2 files changed

+129
-70
lines changed

index.js

+93-65
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ function interpolateAmpInSelector(nodes, parent) {
5353
*/
5454
function mergeSelectors(parent, child) {
5555
let merged = []
56-
parent.selectors.forEach(sel => {
56+
for (let sel of parent.selectors) {
5757
let parentNode = parse(sel, parent)
5858

59-
child.selectors.forEach(selector => {
59+
for (let selector of child.selectors) {
6060
if (!selector) {
61-
return
61+
continue
6262
}
6363
let node = parse(selector, child)
6464
let replaced = interpolateAmpInSelector(node, parentNode)
@@ -67,22 +67,43 @@ function mergeSelectors(parent, child) {
6767
node.prepend(parentNode.clone({}))
6868
}
6969
merged.push(node.toString())
70-
})
71-
})
70+
}
71+
}
7272
return merged
7373
}
7474

7575
/**
76-
* Move a child and its preceeding comment(s) to after "after"
76+
* Move a child and its preceding comment(s) to after "after"
77+
* ! It is necessary to clarify the comment
7778
*/
7879
function breakOut(child, after) {
79-
let prev = child.prev()
80-
after.after(child)
81-
while (prev && prev.type === 'comment') {
82-
let nextPrev = prev.prev()
83-
after.after(prev)
84-
prev = nextPrev
80+
let changeParent = true
81+
82+
for (let node of after.nodes) {
83+
if (!node.nodes) continue
84+
85+
let prevNode = node.prev()
86+
if (prevNode?.type !== 'comment') continue
87+
88+
let parentRule = after.toString()
89+
90+
/* Checking that the comment "describes" the rule following. Like this:
91+
/* comment about the rule below /*
92+
.rule {}
93+
*/
94+
let regexp = new RegExp(`${prevNode.toString()} *\n *${node.toString()}`)
95+
96+
if (parentRule.match(regexp)) {
97+
changeParent = false
98+
after.after(node).after(prevNode)
99+
}
100+
}
101+
102+
// It is necessary if the above child has never been moved
103+
if (changeParent) {
104+
after.after(child)
85105
}
106+
86107
return child
87108
}
88109

@@ -104,14 +125,12 @@ function createFnAtruleChilds(bubble) {
104125
children.push(child)
105126
}
106127
})
107-
if (bubbling) {
108-
if (children.length) {
109-
let clone = rule.clone({ nodes: [] })
110-
for (let child of children) {
111-
clone.append(child)
112-
}
113-
atrule.prepend(clone)
128+
if (bubbling && children.length) {
129+
let clone = rule.clone({ nodes: [] })
130+
for (let child of children) {
131+
clone.append(child)
114132
}
133+
atrule.prepend(clone)
115134
}
116135
}
117136
}
@@ -125,16 +144,23 @@ function pickDeclarations(selector, declarations, after) {
125144
after.after(parent)
126145
return parent
127146
}
147+
function pickAndClearDeclarations(ruleSelector, declarations, after, clear = true) {
148+
if (!declarations.length) return [after, declarations]
128149

129-
function atruleNames(defaults, custom) {
130-
let list = {}
131-
for (let name of defaults) {
132-
list[name] = true
150+
after = pickDeclarations(ruleSelector, declarations, after)
151+
152+
if (clear) {
153+
declarations = []
133154
}
134-
if (custom) {
135-
for (let name of custom) {
136-
list[name.replace(/^@/, '')] = true
137-
}
155+
156+
return [after, declarations]
157+
}
158+
159+
function atruleNames(defaults, custom = '') {
160+
let names = defaults.concat(custom)
161+
let list = {}
162+
for (let name of names) {
163+
list[name.replace(/^@/, '')] = true
138164
}
139165
return list
140166
}
@@ -297,10 +323,10 @@ module.exports = (opts = {}) => {
297323
postcssPlugin: 'postcss-nested',
298324

299325
RootExit(root) {
300-
if (root[hasRootRule]) {
301-
root.walkAtRules(rootRuleName, unwrapRootRule)
302-
root[hasRootRule] = false
303-
}
326+
if (!root[hasRootRule]) return
327+
328+
root.walkAtRules(rootRuleName, unwrapRootRule)
329+
root[hasRootRule] = false
304330
},
305331

306332
Rule(rule) {
@@ -310,46 +336,48 @@ module.exports = (opts = {}) => {
310336
let declarations = []
311337

312338
rule.each(child => {
313-
if (child.type === 'rule') {
314-
if (declarations.length) {
315-
after = pickDeclarations(rule.selector, declarations, after)
316-
declarations = []
317-
}
318-
319-
copyDeclarations = true
320-
unwrapped = true
321-
child.selectors = mergeSelectors(rule, child)
322-
after = breakOut(child, after)
323-
} else if (child.type === 'atrule') {
324-
if (declarations.length) {
325-
after = pickDeclarations(rule.selector, declarations, after)
326-
declarations = []
327-
}
328-
if (child.name === rootRuleName) {
329-
unwrapped = true
330-
atruleChilds(rule, child, true, child[rootRuleMergeSel])
331-
after = breakOut(child, after)
332-
} else if (bubble[child.name]) {
333-
copyDeclarations = true
334-
unwrapped = true
335-
atruleChilds(rule, child, true)
336-
after = breakOut(child, after)
337-
} else if (unwrap[child.name]) {
339+
switch (child.type) {
340+
case 'rule':
341+
[after, declarations] = pickAndClearDeclarations(rule.selector, declarations, after)
342+
338343
copyDeclarations = true
339344
unwrapped = true
340-
atruleChilds(rule, child, false)
345+
child.selectors = mergeSelectors(rule, child)
341346
after = breakOut(child, after)
342-
} else if (copyDeclarations) {
343-
declarations.push(child)
344-
}
345-
} else if (child.type === 'decl' && copyDeclarations) {
346-
declarations.push(child)
347+
348+
break
349+
case 'atrule':
350+
[after, declarations] = pickAndClearDeclarations(rule.selector, declarations, after)
351+
352+
if (child.name === rootRuleName) {
353+
unwrapped = true
354+
atruleChilds(rule, child, true, child[rootRuleMergeSel])
355+
after = breakOut(child, after)
356+
} else if (bubble[child.name]) {
357+
copyDeclarations = true
358+
unwrapped = true
359+
atruleChilds(rule, child, true)
360+
after = breakOut(child, after)
361+
} else if (unwrap[child.name]) {
362+
copyDeclarations = true
363+
unwrapped = true
364+
atruleChilds(rule, child, false)
365+
after = breakOut(child, after)
366+
} else if (copyDeclarations) {
367+
declarations.push(child)
368+
}
369+
370+
break
371+
case 'decl':
372+
if (copyDeclarations) {
373+
declarations.push(child)
374+
}
375+
376+
break
347377
}
348378
})
349379

350-
if (declarations.length) {
351-
after = pickDeclarations(rule.selector, declarations, after)
352-
}
380+
pickAndClearDeclarations(rule.selector, declarations, after, false)
353381

354382
if (unwrapped && preserveEmpty !== true) {
355383
rule.raws.semicolon = true

index.test.js

+36-5
Original file line numberDiff line numberDiff line change
@@ -604,16 +604,47 @@ test('clears empty selector after comma', () => {
604604
run('a, b { .one, .two, {} }', 'a .one, a .two, b .one, b .two {}')
605605
})
606606

607-
test('moves comment with rule', () => {
608-
run('a { /*B*/ /*B2*/ b {} }', '/*B*/ /*B2*/ a b {}')
607+
test("Save the parent's comment", () => {
608+
run('a { /*i*/ b {} }', 'a { /*i*/ } a b {}')
609609
})
610610

611-
test('moves comment with at-rule', () => {
612-
run('a { /*B*/ @media { one: 1 } }', '/*B*/ @media {a { one: 1 } }')
611+
test("Save the parent's comment with newline", () => {
612+
run(
613+
`a {
614+
/*i*/
615+
616+
b {} }`,
617+
`a { /*i*/ } a b {}`
618+
)
619+
})
620+
621+
test('Save the comments for the parent and child', () => {
622+
run(
623+
`a {
624+
/*i*/
625+
/*o*/
626+
b {} }`,
627+
628+
`a { /*i*/ } /*o*/ a b {}`
629+
)
630+
})
631+
632+
test('Save the comments for the parent and child with at-rule', () => {
633+
run(
634+
`a { /*i*/
635+
/*o*/
636+
@media { one: 1 } }`,
637+
638+
`a { /*i*/ } /*o*/ @media {a { one: 1 } }`
639+
)
613640
})
614641

615642
test('moves comment with declaration', () => {
616-
run('a { @media { /*B*/ one: 1 } }', '@media {a { /*B*/ one: 1 } }')
643+
run('a { @media { /*B*/ one: 1 } }', '@media { a { /*B*/ one: 1 } }')
644+
})
645+
646+
test('moves comment with declaration without properties', () => {
647+
run('a { @media { /*B*/ } }', '@media { a { /*B*/ } }')
617648
})
618649

619650
test('saves order of rules', () => {

0 commit comments

Comments
 (0)