Files
old-cto-as-you-go/CTOAsYouGo/node_modules/postcss-nested/index.js

208 lines
5.0 KiB
JavaScript
Raw Normal View History

2023-07-05 11:02:15 +02:00
var postcss = require('postcss')
var parser = require('postcss-selector-parser')
2023-07-01 10:42:40 +02:00
2023-07-05 11:02:15 +02:00
function parse (str, rule) {
var nodes
var saver = parser(function (parsed) {
nodes = parsed
})
2023-07-01 10:42:40 +02:00
try {
2023-07-05 11:02:15 +02:00
saver.processSync(str)
2023-07-01 10:42:40 +02:00
} catch (e) {
2023-07-05 11:02:15 +02:00
if (str.indexOf(':') !== -1) {
2023-07-01 10:42:40 +02:00
throw rule ? rule.error('Missed semicolon') : e
} else {
throw rule ? rule.error(e.message) : e
}
}
return nodes.at(0)
}
2023-07-05 11:02:15 +02:00
function replace (nodes, parent) {
var replaced = false
nodes.each(function (i) {
if (i.type === 'nesting') {
var clonedParent = parent.clone()
if (i.value !== '&') {
i.replaceWith(parse(i.value.replace('&', clonedParent.toString())))
2023-07-01 10:42:40 +02:00
} else {
2023-07-05 11:02:15 +02:00
i.replaceWith(clonedParent)
2023-07-01 10:42:40 +02:00
}
replaced = true
2023-07-05 11:02:15 +02:00
} else if (i.nodes) {
if (replace(i, parent)) {
2023-07-01 10:42:40 +02:00
replaced = true
}
}
})
return replaced
}
2023-07-05 11:02:15 +02:00
function selectors (parent, child) {
var result = []
parent.selectors.forEach(function (i) {
var parentNode = parse(i, parent)
2023-07-01 10:42:40 +02:00
2023-07-05 11:02:15 +02:00
child.selectors.forEach(function (j) {
var node = parse(j, child)
var replaced = replace(node, parentNode)
2023-07-01 10:42:40 +02:00
if (!replaced) {
node.prepend(parser.combinator({ value: ' ' }))
2023-07-05 11:02:15 +02:00
node.prepend(parentNode.clone())
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
result.push(node.toString())
2023-07-01 10:42:40 +02:00
})
})
2023-07-05 11:02:15 +02:00
return result
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
function pickComment (comment, after) {
if (comment && comment.type === 'comment') {
after.after(comment)
return comment
} else {
return after
2023-07-01 10:42:40 +02:00
}
}
2023-07-05 11:02:15 +02:00
function atruleChilds (rule, atrule, bubbling) {
var children = []
atrule.each(function (child) {
if (child.type === 'comment') {
children.push(child)
} else if (child.type === 'decl') {
children.push(child)
} else if (child.type === 'rule' && bubbling) {
child.selectors = selectors(rule, child)
} else if (child.type === 'atrule') {
atruleChilds(rule, child, bubbling)
}
})
if (bubbling) {
if (children.length) {
var clone = rule.clone({ nodes: [] })
for (var i = 0; i < children.length; i++) {
clone.append(children[i])
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
atrule.prepend(clone)
2023-07-01 10:42:40 +02:00
}
}
}
2023-07-05 11:02:15 +02:00
function pickDeclarations (selector, declarations, after) {
var parent = postcss.rule({
selector: selector,
2023-07-01 10:42:40 +02:00
nodes: []
})
2023-07-05 11:02:15 +02:00
for (var i = 0; i < declarations.length; i++) {
parent.append(declarations[i])
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
after.after(parent)
return parent
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
function processRule (rule, bubble, unwrap, preserveEmpty) {
var unwrapped = false
var after = rule
var copyDeclarations = false
var declarations = []
2023-07-01 10:42:40 +02:00
2023-07-05 11:02:15 +02:00
rule.each(function (child) {
if (child.type === 'rule') {
if (declarations.length) {
after = pickDeclarations(rule.selector, declarations, after)
declarations = []
}
2023-07-01 10:42:40 +02:00
2023-07-05 11:02:15 +02:00
copyDeclarations = true
unwrapped = true
child.selectors = selectors(rule, child)
after = pickComment(child.prev(), after)
after.after(child)
after = child
} else if (child.type === 'atrule') {
copyDeclarations = false
2023-07-01 10:42:40 +02:00
2023-07-05 11:02:15 +02:00
if (declarations.length) {
after = pickDeclarations(rule.selector, declarations, after)
declarations = []
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
if (child.name === 'at-root') {
unwrapped = true
atruleChilds(rule, child, false)
2023-07-01 10:42:40 +02:00
2023-07-05 11:02:15 +02:00
var nodes = child.nodes
if (child.params) {
nodes = postcss.rule({
selector: child.params,
nodes: nodes
})
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
after.after(nodes)
after = nodes
child.remove()
} else if (bubble[child.name]) {
unwrapped = true
atruleChilds(rule, child, true)
after = pickComment(child.prev(), after)
after.after(child)
after = child
} else if (unwrap[child.name]) {
unwrapped = true
atruleChilds(rule, child, false)
after = pickComment(child.prev(), after)
after.after(child)
after = child
}
} else if (child.type === 'decl' && copyDeclarations) {
declarations.push(child)
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
})
if (declarations.length) {
after = pickDeclarations(rule.selector, declarations, after)
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
if (unwrapped && preserveEmpty !== true) {
rule.raws.semicolon = true
if (rule.nodes.length === 0) rule.remove()
}
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
function atruleNames (defaults, custom) {
var list = { }
var i, name
for (i = 0; i < defaults.length; i++) {
list[defaults[i]] = true
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
if (custom) {
for (i = 0; i < custom.length; i++) {
name = custom[i].replace(/^@/, '')
list[name] = true
}
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
return list
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
module.exports = postcss.plugin('postcss-nested', function (opts) {
if (!opts) opts = { }
var bubble = atruleNames(['media', 'supports'], opts.bubble)
var unwrap = atruleNames(['document', 'font-face', 'keyframes'], opts.unwrap)
var preserveEmpty = opts ? opts.preserveEmpty : false
var process = function (node) {
node.each(function (child) {
if (child.type === 'rule') {
processRule(child, bubble, unwrap, preserveEmpty)
} else if (child.type === 'atrule') {
process(child)
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
})
2023-07-01 10:42:40 +02:00
}
2023-07-05 11:02:15 +02:00
return process
})