Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
root.each(function rewriteSelector (node) {
if (!node.selector) {
// handle media queries
if (node.type === 'atrule') {
if (node.name === 'media' || node.name === 'supports') {
node.each(rewriteSelector)
} else if (/-?keyframes$/.test(node.name)) {
// register keyframes
keyframes[node.params] = node.params = node.params + '-' + id
}
}
return
}
node.selector = selectorParser(selectors => {
selectors.each(selector => {
let node = null
selector.each(n => {
// ">>>" combinator
if (n.type === 'combinator' && n.value === '>>>') {
n.value = ' '
n.spaces.before = n.spaces.after = ''
return false
}
// /deep/ alias for >>>, since >>> doesn't work in SASS
if (n.type === 'tag' && n.value === '/deep/') {
const prev = n.prev()
if (prev && prev.type === 'combinator' && prev.value === ' ') {
prev.remove()
}
n.remove()
}
if (n.type === 'pseudo') {
// deep: inject [id] attribute at the node before the ::v-deep
// combinator.
if (n.value === '::v-deep') {
if (n.nodes.length) {
// .foo ::v-deep(.bar) -> .foo[xxxxxxx] .bar
// replace the current node with ::v-deep's inner selector
selector.insertAfter(n, n.nodes[0])
// insert a space combinator before if it doesn't already have one
const prev = selector.at(selector.index(n) - 1)
if (!prev || !isSpaceCombinator(prev)) {
selector.insertAfter(
n,
selectorParser.combinator({
value: ' '
})
)
}
selector.removeChild(n)
} else {
// DEPRECATED usage
// .foo ::v-deep .bar -> .foo[xxxxxxx] .bar
console.warn(
`[@vue/compiler-sfc] ::v-deep usage as a combinator has ` +
`been deprecated. Use ::v-deep() instead.`
)
const prev = selector.at(selector.index(n) - 1)
if (prev && isSpaceCombinator(prev)) {
selector.removeChild(prev)
}
) {
annotation.remove()
return
}
if (node.parent && node.parent.type === 'atrule' && node.parent.name === 'keyframes') {
return
}
if (this.hasIgnoreAnnotation(node)) {
return
}
let keepSelector = true
node.selector = selectorParser(selectorsParsed => {
selectorsParsed.walk(selector => {
const selectorsInRule = []
if (selector.type === 'selector') {
// if inside :not pseudo class, ignore
if (
selector.parent &&
selector.parent.value === ':not' &&
selector.parent.type === 'pseudo'
) {
return
}
for (const { type, value } of selector.nodes) {
if (
SELECTOR_STANDARD_TYPES.includes(type) &&
typeof value !== 'undefined'
) {
resolvedNestedSelector(selector, rule).forEach(resolvedSelector => {
// Process each resolved selector with `checkSelector` via postcss-selector-parser
selectorParser(s => checkSelector(s, rule)).process(resolvedSelector)
})
})
node = n
}
})
if (node) {
node.spaces.after = ''
} else {
// For deep selectors & standalone pseudo selectors,
// the attribute selectors are prepended rather than appended.
// So all leading spaces must be eliminated to avoid problems.
selector.first.spaces.before = ''
}
selector.insertAfter(
node,
selectorParser.attribute({
attribute: id
})
)
})
}).processSync(node.selector)
// Compound selectors containing :host have a special treatment and should not be scoped
// like the rest of the complex selectors.
const containsHost = compoundSelector.some(isHostPseudoClass);
if (!containsSingleDirSelector && !containsHost) {
let nodeToScope: Node | undefined;
// In each compound selector we need to locate the last selector to scope.
for (const node of compoundSelector) {
if (!isPseudoElement(node)) {
nodeToScope = node;
}
}
const shadowAttribute = attribute({
attribute: SHADOW_ATTRIBUTE,
value: undefined,
raws: {},
});
if (nodeToScope) {
// Add the scoping attribute right after the node scope
selector.insertAfter(nodeToScope, shadowAttribute);
} else {
// Add the scoping token in the first position of the compound selector as a fallback
// when there is no node to scope. For example: ::after {}
selector.insertBefore(compoundSelector[0], shadowAttribute);
}
}
}
}
function transformHost(selector: Selector) {
// Locate the first :host pseudo-class
const hostNode = findNode(selector, isHostPseudoClass) as Pseudo | undefined;
if (hostNode) {
// Store the original location of the :host in the selector
const hostIndex = selector.index(hostNode);
// Swap the :host pseudo-class with the host scoping token
const hostAttribute = attribute({
attribute: HOST_ATTRIBUTE,
value: undefined,
raws: {},
});
hostNode.replaceWith(hostAttribute);
// Generate a unique contextualized version of the selector for each selector pass as argument
// to the :host
const contextualSelectors = hostNode.nodes.map((contextSelectors: Selector) => {
const clonedSelector = selector.clone({}) as Selector;
const clonedHostNode = clonedSelector.at(hostIndex) as Tag;
// Add to the compound selector previously containing the :host pseudo class
// the contextual selectors.
contextSelectors.each(node => {
trimNodeWhitespaces(node);
}
n.remove()
return false
} else if (isInvalidTag(n.value)) {
return
}
}
if (n.type !== 'pseudo' && n.type !== 'combinator') {
target = n
}
})
/* eslint-enable complexity */
target && selector.insertAfter(target, selectorParser.attribute({
attribute: scopeID
}))
})
})
// /deep/ alias for >>>, since >>> doesn't work in SASS
if (n.type === 'tag' && n.value === '/deep/') {
var next = n.next();
if (next.type === 'combinator' && next.value === ' ') {
next.remove();
}
n.remove();
return false;
}
if (n.type !== 'pseudo' && n.type !== 'combinator') {
node = n;
}
});
selector.insertAfter(
node,
selectorParser.attribute({
attribute: opts.id,
})
);
});
}).process(node.selector).result;
return false
}
// /deep/ alias for >>>, since >>> doesn't work in SASS
if (n.type === 'tag' && n.value === '/deep/') {
const prev = n.prev()
if (prev && prev.type === 'combinator' && prev.value === ' ') {
prev.remove()
}
n.remove()
return false
}
if (n.type !== 'pseudo' && n.type !== 'combinator') {
node = n
}
})
selector.insertAfter(node, selectorParser.attribute({
attribute: id
}))
})
}).processSync(node.selector)