Selector parser with built in methods for working with selector strings.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Runtime type checking functions for identifying and validating AST node types. Essential for safely working with the parsed AST and implementing type-specific logic.
Core functions for validating nodes and their capabilities.
/**
* Check if value is a valid AST node
* @param node - Value to check
* @returns True if value is a node
*/
function isNode(node: any): boolean;
/**
* Check if node is a container (can have children)
* @param node - Node to check
* @returns True if node is Root, Selector, or Pseudo
*/
function isContainer(node: any): boolean;
/**
* Check if node supports namespaces
* @param node - Node to check
* @returns True if node is Attribute or Tag
*/
function isNamespace(node: any): boolean;Usage Examples:
const parser = require('postcss-selector-parser');
const ast = parser().astSync('.class, #id');
const node = ast.first.first;
// Check if it's a valid node
if (parser.isNode(node)) {
console.log('Valid node:', node.type);
}
// Check if it can contain children
if (parser.isContainer(node)) {
console.log('Can contain children');
node.walk(child => {
console.log('Child:', child.type);
});
}
// Check if it supports namespaces
if (parser.isNamespace(node)) {
console.log('Supports namespaces');
console.log('Namespace:', node.namespace);
}Functions for identifying specific container node types.
/**
* Check if node is a Root container
* @param node - Node to check
* @returns True if node is Root
*/
function isRoot(node: any): boolean;
/**
* Check if node is a Selector container
* @param node - Node to check
* @returns True if node is Selector
*/
function isSelector(node: any): boolean;
/**
* Check if node is a Pseudo container
* @param node - Node to check
* @returns True if node is Pseudo
*/
function isPseudo(node: any): boolean;Usage Examples:
const parser = require('postcss-selector-parser');
const ast = parser().astSync('.class:hover');
// Check root
if (parser.isRoot(ast)) {
console.log('This is the root container');
console.log('Selectors:', ast.nodes.length);
}
// Check selector
const firstChild = ast.first;
if (parser.isSelector(firstChild)) {
console.log('This is a selector');
console.log('Components:', firstChild.nodes.length);
}
// Check pseudo
const pseudo = firstChild.last;
if (parser.isPseudo(pseudo)) {
console.log('This is a pseudo selector');
console.log('Value:', pseudo.value);
}Functions for identifying specific leaf node types that cannot contain children.
/**
* Check if node is an Attribute selector
* @param node - Node to check
* @returns True if node is Attribute
*/
function isAttribute(node: any): boolean;
/**
* Check if node is a ClassName selector
* @param node - Node to check
* @returns True if node is ClassName
*/
function isClassName(node: any): boolean;
/**
* Check if node is a Combinator
* @param node - Node to check
* @returns True if node is Combinator
*/
function isCombinator(node: any): boolean;
/**
* Check if node is a Comment
* @param node - Node to check
* @returns True if node is Comment
*/
function isComment(node: any): boolean;
/**
* Check if node is an Identifier (ID selector)
* @param node - Node to check
* @returns True if node is Identifier
*/
function isIdentifier(node: any): boolean;
/**
* Check if node is a Nesting selector
* @param node - Node to check
* @returns True if node is Nesting
*/
function isNesting(node: any): boolean;
/**
* Check if node is a String literal
* @param node - Node to check
* @returns True if node is String
*/
function isString(node: any): boolean;
/**
* Check if node is a Tag selector
* @param node - Node to check
* @returns True if node is Tag
*/
function isTag(node: any): boolean;
/**
* Check if node is a Universal selector
* @param node - Node to check
* @returns True if node is Universal
*/
function isUniversal(node: any): boolean;Usage Examples:
const parser = require('postcss-selector-parser');
const ast = parser().astSync('div.class#id[href] > * + /* comment */');
const selector = ast.first;
// Walk through nodes and identify types
selector.walk(node => {
if (parser.isTag(node)) {
console.log('Tag:', node.value);
} else if (parser.isClassName(node)) {
console.log('Class:', node.value);
} else if (parser.isIdentifier(node)) {
console.log('ID:', node.value);
} else if (parser.isAttribute(node)) {
console.log('Attribute:', node.attribute);
} else if (parser.isCombinator(node)) {
console.log('Combinator:', node.value);
} else if (parser.isUniversal(node)) {
console.log('Universal selector');
} else if (parser.isComment(node)) {
console.log('Comment:', node.value);
}
});Specialized functions for distinguishing between pseudo-classes and pseudo-elements.
/**
* Check if node is specifically a pseudo-element
* @param node - Node to check
* @returns True if node is a pseudo-element
*/
function isPseudoElement(node: any): boolean;
/**
* Check if node is specifically a pseudo-class
* @param node - Node to check
* @returns True if node is a pseudo-class
*/
function isPseudoClass(node: any): boolean;Usage Examples:
const parser = require('postcss-selector-parser');
const ast = parser().astSync('.btn:hover::before:first-letter');
const selector = ast.first;
selector.walkPseudos(pseudo => {
if (parser.isPseudoElement(pseudo)) {
console.log('Pseudo-element:', pseudo.value);
// Outputs: ::before, :first-letter
} else if (parser.isPseudoClass(pseudo)) {
console.log('Pseudo-class:', pseudo.value);
// Outputs: :hover
}
});
// Specific pseudo-element detection
const pseudos = [':before', ':after', '::before', '::after', ':first-letter', ':first-line'];
pseudos.forEach(pseudoValue => {
const node = parser.pseudo({ value: pseudoValue });
console.log(`${pseudoValue} is pseudo-element:`, parser.isPseudoElement(node));
});Using type guards for safe node processing and transformation.
Usage Examples:
const parser = require('postcss-selector-parser');
// Transform function using type guards
const transform = selectors => {
selectors.walk(node => {
// Remove universal selectors
if (parser.isUniversal(node)) {
node.remove();
return;
}
// Convert all IDs to classes
if (parser.isIdentifier(node)) {
const className = parser.className({ value: node.value });
node.replaceWith(className);
return;
}
// Add namespace to tags
if (parser.isTag(node)) {
node.namespace = 'app';
return;
}
// Process attributes
if (parser.isAttribute(node)) {
if (node.attribute === 'class') {
// Convert [class="value"] to .value
if (node.operator === '=' && node.value) {
const className = parser.className({ value: node.value });
node.replaceWith(className);
}
}
return;
}
});
};
const processor = parser(transform);
const result = processor.processSync('*#header.nav[class="btn"]');
// Result: app|#header.nav.btnCombining type guards for complex logic and validation.
Usage Examples:
const parser = require('postcss-selector-parser');
// Function to analyze selector complexity
function analyzeSelector(selectorString) {
const ast = parser().astSync(selectorString);
const stats = {
selectors: 0,
tags: 0,
classes: 0,
ids: 0,
attributes: 0,
pseudoClasses: 0,
pseudoElements: 0,
combinators: 0,
hasNamespaces: false,
hasComments: false
};
ast.walk(node => {
if (parser.isSelector(node)) {
stats.selectors++;
} else if (parser.isTag(node)) {
stats.tags++;
if (parser.isNamespace(node) && node.namespace) {
stats.hasNamespaces = true;
}
} else if (parser.isClassName(node)) {
stats.classes++;
} else if (parser.isIdentifier(node)) {
stats.ids++;
} else if (parser.isAttribute(node)) {
stats.attributes++;
} else if (parser.isPseudoClass(node)) {
stats.pseudoClasses++;
} else if (parser.isPseudoElement(node)) {
stats.pseudoElements++;
} else if (parser.isCombinator(node)) {
stats.combinators++;
} else if (parser.isComment(node)) {
stats.hasComments = true;
}
});
return stats;
}
// Usage
const stats = analyzeSelector('div.nav#main[data-id] > .item:hover::before');
console.log(stats);
// { selectors: 1, tags: 1, classes: 2, ids: 1, attributes: 1,
// pseudoClasses: 1, pseudoElements: 1, combinators: 1, ... }Install with Tessl CLI
npx tessl i tessl/npm-postcss-selector-parser